/[thuban]/trunk/thuban/test/test_save.py
ViewVC logotype

Diff of /trunk/thuban/test/test_save.py

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

revision 494 by jonathan, Mon Mar 10 10:45:33 2003 UTC revision 2551 by jonathan, Thu Jan 27 14:19:41 2005 UTC
# Line 1  Line 1 
1  # Copyright (c) 2002 by Intevation GmbH  # Copyright (c) 2002, 2003, 2004 by Intevation GmbH
2  # Authors:  # Authors:
3  # Bernhard Herzog <[email protected]>  # Bernhard Herzog <[email protected]>
4  #  #
# Line 17  import os Line 17  import os
17  import unittest  import unittest
18  from StringIO import StringIO  from StringIO import StringIO
19    
20  import xml.sax  import xmlsupport
21  import xml.sax.handler  import postgissupport
 from xml.sax import make_parser, ErrorHandler  
22    
23  import support  import support
24  support.initthuban()  support.initthuban()
25    
26  from Thuban.Model.save import save_session  import dbflib
27    
28    from Thuban.Lib.fileutil import relative_filename
29    from Thuban.Model.save import XMLWriter, save_session, sort_data_stores
30  from Thuban.Model.session import Session  from Thuban.Model.session import Session
31  from Thuban.Model.map import Map  from Thuban.Model.map import Map
32  from Thuban.Model.layer import Layer  from Thuban.Model.layer import Layer, RasterLayer
33  from Thuban.Model.proj import Projection  from Thuban.Model.proj import Projection
34    from Thuban.Model.table import DBFTable
35    from Thuban.Model.transientdb import TransientJoinedTable
36  class SaxEventLister(xml.sax.handler.ContentHandler):  from Thuban.Model.data import DerivedShapeStore
37    
38      def __init__(self):  from Thuban.Model.classification import ClassGroupSingleton, ClassGroupRange, \
39          self.eventlist = []      ClassGroupProperties
40    
41      def startElementNS(self, name, qname, attrs):  from Thuban.Model.range import Range
42          items = attrs.items()  
43          items.sort()  from Thuban.Model.postgisdb import PostGISConnection, PostGISShapeStore
44          self.eventlist.append(("start", name, qname, items))  
45    
46      def endElementNS(self, name, qname):  class XMLWriterTest(unittest.TestCase):
47          self.eventlist.append(("end", name, qname))  
48        def testEncode(self):
49            """Test XMLWriter.encode"""
50  def sax_eventlist(data):          writer = XMLWriter()
51      """Return a list of SAX event generated for the XML data.          eq = self.assertEquals
52      """  
53      handler = SaxEventLister()          eq(writer.encode("hello world"), "hello world")
54      parser = make_parser()          eq(writer.encode(unicode("hello world")), unicode("hello world"))
55      parser.setContentHandler(handler)  
56      parser.setErrorHandler(ErrorHandler())          eq(writer.encode("\x80\x90\xc2\x100"),
57      parser.setFeature(xml.sax.handler.feature_namespaces, 1)                           "\xc2\x80\xc2\x90\xc3\x82\x100")
58            eq(writer.encode(u"\x80\x90\xc2\x100"),
59      inpsrc = xml.sax.InputSource()                           "\xc2\x80\xc2\x90\xc3\x82\x100")
60      inpsrc.setByteStream(StringIO(data))          eq(writer.encode(u"\xFF5E"), "\xc3\xbf5E")
61      parser.parse(inpsrc)  
62            eq(writer.encode('&"\'<>'), "&amp;&quot;&apos;&lt;&gt;")
63      return handler.eventlist          eq(writer.encode(unicode('&"\'<>')), "&amp;&quot;&apos;&lt;&gt;")
64    
65  class SaveSessionTest(unittest.TestCase, support.FileTestMixin):  class SaveSessionTest(unittest.TestCase, support.FileTestMixin,
66                          xmlsupport.ValidationTest):
67    
68        dtd = "http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd"
69        thubanids = [((dtd, n), (None, "id")) for n in
70                     ["fileshapesource", "filetable", "jointable",
71                      "derivedshapesource", "dbshapesource", "dbconnection"]]
72        thubanidrefs = [((dtd, n), (None, m)) for n, m in
73                        [("layer", "shapestore"),
74                         ("jointable", "left"),
75                         ("jointable", "right"),
76                         ("derivedshapesource", "table"),
77                         ("derivedshapesource", "shapesource"),
78                         ("dbshapesource", "dbconn")]]
79        del n, m, dtd
80    
81        def tearDown(self):
82            """Call self.session.Destroy
83    
84            Test cases that create session should bind it to self.session so
85            that it gets destroyed properly
86            """
87            if hasattr(self, "session"):
88                self.session.Destroy()
89                self.session = None
90    
91      def compare_xml(self, xml1, xml2):      def compare_xml(self, xml1, xml2):
92          self.assertEquals(sax_eventlist(xml1), sax_eventlist(xml2))          list1 = xmlsupport.sax_eventlist(xml1, ids = self.thubanids,
93                                             idrefs = self.thubanidrefs)
94            list2 = xmlsupport.sax_eventlist(xml2, ids = self.thubanids,
95                                             idrefs = self.thubanidrefs)
96            if list1 != list2:
97                for a, b in zip(list1, list2):
98                    if a != b:
99                        self.fail("%r != %r" % (a, b))
100    
101    
102      def testEmptySession(self):      def testEmptySession(self):
103          """Save an empty session"""          """Save an empty session"""
# Line 77  class SaveSessionTest(unittest.TestCase, Line 111  class SaveSessionTest(unittest.TestCase,
111          file.close()          file.close()
112          self.compare_xml(written_contents,          self.compare_xml(written_contents,
113                           '<?xml version="1.0" encoding="UTF-8"?>\n'                           '<?xml version="1.0" encoding="UTF-8"?>\n'
114                           '<!DOCTYPE session SYSTEM "thuban.dtd">\n'                           '<!DOCTYPE session SYSTEM "thuban-1.1.dtd">\n'
115                           '<session title="empty session">\n</session>\n')                           '<session title="empty session" '
116             'xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">'
117                             '\n</session>\n')
118    
119            self.validate_data(written_contents)
120    
121      def testSingleLayer(self):      def testSingleLayer(self):
122          """Save a session with a single map with a single layer"""          """Save a session with a single map with a single layer"""
123          # deliberately put an apersand in the title :)          # deliberately put an apersand in the title :)
124          session = Session("single map&layer")          session = Session("single map&layer")
125          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])          proj = Projection(["proj=utm", "zone=27", "ellps=WGS84",
126                               "datum=WGS84", "units=m"],
127                              name = "WGS 84 / UTM zone 27N",
128                              epsg = "32627")
129          map = Map("Test Map", projection = proj)          map = Map("Test Map", projection = proj)
130          session.AddMap(map)          session.AddMap(map)
131          # use shapefile from the example data          # use shapefile from the example data
132          shpfile = os.path.join(os.path.dirname(__file__),          shpfile = os.path.join(os.path.dirname(__file__),
133                                 os.pardir, "Data", "iceland", "political.shp")                                 os.pardir, "Data", "iceland", "political.shp")
134          layer = Layer("My Layer", shpfile)          layer = Layer("My Layer", session.OpenShapefile(shpfile))
135          map.AddLayer(layer)          map.AddLayer(layer)
136    
137          filename = self.temp_file_name("save_singlemap.thuban")          filename = self.temp_file_name("save_singlemap.thuban")
138          save_session(session, filename)          save_session(session, filename)
139    
140            file = open(filename)
141            written_contents = file.read()
142            file.close()
143            expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
144            <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
145            <session title="single map&amp;layer"
146               xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">
147                <fileshapesource id="D1"
148                    filename="../../Data/iceland/political.shp"
149                    filetype="shapefile"/>
150                <map title="Test Map">
151                    <projection epsg="32627" name="WGS 84 / UTM zone 27N">
152                        <parameter value="proj=utm"/>
153                        <parameter value="zone=27"/>
154                        <parameter value="ellps=WGS84"/>
155                        <parameter value="datum=WGS84"/>
156                        <parameter value="units=m"/>
157                    </projection>
158                    <layer title="My Layer" shapestore="D1"
159                    fill="None" stroke="#000000" stroke_width="1" visible="%s"/>
160                </map>
161            </session>'''
162    
163            expected_contents = expected_template % "true"
164    
165            self.compare_xml(written_contents, expected_contents)
166    
167            self.validate_data(written_contents)
168    
169            # Repeat with an invisible layer
170            layer.SetVisible(False)
171            save_session(session, filename)
172    
173            file = open(filename)
174            written_contents = file.read()
175            file.close()
176            expected_contents = expected_template % "false"
177            self.compare_xml(written_contents, expected_contents)
178            self.validate_data(written_contents)
179    
180            session.Destroy()
181    
182        def testLayerProjection(self):
183            """Test saving layers with projections"""
184            # deliberately put an apersand in the title :)
185            session = self.session = Session("single map&layer")
186            proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
187            map = Map("Test Map", projection = proj)
188            session.AddMap(map)
189            # use shapefile from the example data
190            shpfile = os.path.join(os.path.dirname(__file__),
191                                   os.pardir, "Data", "iceland", "political.shp")
192            layer = Layer("My Layer", session.OpenShapefile(shpfile))
193            proj = Projection(["proj=lcc", "ellps=clrk66",
194                               "lat_1=0", "lat_2=20"],
195                              "Layer Projection")
196            layer.SetProjection(proj)
197            map.AddLayer(layer)
198    
199            filename = self.temp_file_name("save_layerproj.thuban")
200            save_session(session, filename)
201    
202            file = open(filename)
203            written_contents = file.read()
204            file.close()
205            expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
206            <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
207            <session title="single map&amp;layer"
208               xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">
209                <fileshapesource id="D1"
210                    filename="../../Data/iceland/political.shp"
211                    filetype="shapefile"/>
212                <map title="Test Map">
213                    <projection name="Unknown">
214                        <parameter value="zone=26"/>
215                        <parameter value="proj=utm"/>
216                        <parameter value="ellps=clrk66"/>
217                    </projection>
218                    <layer title="My Layer" shapestore="D1"
219                    fill="None" stroke="#000000" stroke_width="1" visible="true">
220                        <projection name="Layer Projection">
221                            <parameter value="proj=lcc"/>
222                            <parameter value="ellps=clrk66"/>
223                            <parameter value="lat_1=0"/>
224                            <parameter value="lat_2=20"/>
225                        </projection>
226                    </layer>
227                </map>
228            </session>'''
229            #print written_contents
230            #print "********************************************"
231            #print expected_contents
232            self.compare_xml(written_contents, expected_contents)
233    
234            self.validate_data(written_contents)
235    
236        def testRasterLayer(self):
237            # deliberately put an apersand in the title :)
238            session = Session("single map&layer")
239            map = Map("Test Map")
240            session.AddMap(map)
241            # use shapefile from the example data
242            imgfile = os.path.join(os.path.dirname(__file__),
243                                   os.pardir, "Data", "iceland", "island.tif")
244            layer = RasterLayer("My RasterLayer", imgfile)
245            layer.SetUseMask(True)
246            map.AddLayer(layer)
247    
248            filename = self.temp_file_name("%s.thuban" % self.id())
249            save_session(session, filename)
250          session.Destroy()          session.Destroy()
251    
252          file = open(filename)          file = open(filename)
253          written_contents = file.read()          written_contents = file.read()
254          file.close()          file.close()
255          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
256          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
257          <session title="single map&amp;layer">          <session title="single map&amp;layer"
258               xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">
259              <map title="Test Map">              <map title="Test Map">
260                  <projection>                  <rasterlayer title="My RasterLayer"
261                            filename="../../Data/iceland/island.tif"
262                            visible="true" use_mask="true">
263                    </rasterlayer>
264                </map>
265            </session>'''
266            #print written_contents
267            #print "********************************************"
268            #print expected_contents
269            self.compare_xml(written_contents, expected_contents)
270    
271            self.validate_data(written_contents)
272    
273        def testClassifiedLayer(self):
274            """Save a session with a single map with classifications"""
275            # deliberately put an apersand in the title :)
276            session = Session("Map with Classifications")
277            proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
278            map = Map("Test Map", projection = proj)
279            session.AddMap(map)
280            # use shapefile from the example data
281            shpfile = os.path.join(os.path.dirname(__file__),
282                                   os.pardir, "Data", "iceland", "political.shp")
283            layer = Layer("My Layer", session.OpenShapefile(shpfile))
284            map.AddLayer(layer)
285            layer2 = Layer("My Layer", layer.ShapeStore())
286            map.AddLayer(layer2)
287    
288            clazz = layer.GetClassification()
289    
290            layer.SetClassificationColumn("AREA")
291    
292            clazz.AppendGroup(ClassGroupSingleton(42, ClassGroupProperties(),
293                                                  "single"))
294            clazz.AppendGroup(ClassGroupSingleton("text", ClassGroupProperties(),
295                                                  "single-text"))
296    
297            clazz.AppendGroup(ClassGroupRange((0, 42),
298                                               ClassGroupProperties(),
299                                               "range"))
300    
301            range = ClassGroupRange(Range("[0;42]"))
302            range.SetProperties(ClassGroupProperties())
303            range.SetLabel("new-range")
304            clazz.AppendGroup(range)
305    
306    
307            clazz = layer2.GetClassification()
308            layer2.SetClassificationColumn("POPYCOUN")
309    
310            # Classification with Latin 1 text
311            clazz.AppendGroup(ClassGroupSingleton('\xe4\xf6\xfc', # ae, oe, ue
312                                                  ClassGroupProperties(),
313                                                  '\xdcml\xe4uts')) # Uemlaeuts
314    
315    
316            filename = self.temp_file_name("%s.thuban" % self.id())
317            save_session(session, filename)
318    
319            file = open(filename)
320            written_contents = file.read()
321            file.close()
322            expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
323            <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
324            <session title="Map with Classifications"
325               xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">
326                <fileshapesource id="D1"
327                    filename="../../Data/iceland/political.shp"
328                    filetype="shapefile"/>
329                <map title="Test Map">
330                    <projection name="Unknown">
331                      <parameter value="zone=26"/>                      <parameter value="zone=26"/>
332                      <parameter value="proj=utm"/>                      <parameter value="proj=utm"/>
333                      <parameter value="ellps=clrk66"/>                      <parameter value="ellps=clrk66"/>
334                  </projection>                  </projection>
335                  <layer title="My Layer" filename="%s"                  <layer title="My Layer" shapestore="D1"
336                  fill="None" stroke="#000000" stroke_width="1"/>                  fill="None" stroke="#000000" stroke_width="1" visible="true">
337                        <classification field="AREA" field_type="double">
338                            <clnull label="">
339                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
340                            </clnull>
341                            <clpoint value="42" label="single">
342                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
343                            </clpoint>
344                            <clpoint value="text" label="single-text">
345                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
346                            </clpoint>
347                            <clrange range="[0;42[" label="range">
348                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
349                            </clrange>
350                            <clrange range="[0;42]" label="new-range">
351                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
352                            </clrange>
353                        </classification>
354                    </layer>
355                    <layer title="My Layer" shapestore="D1"
356                    fill="None" stroke="#000000" stroke_width="1" visible="true">
357                        <classification field="POPYCOUN" field_type="string">
358                            <clnull label="">
359                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
360                            </clnull>
361                            <clpoint value="\xc3\xa4\xc3\xb6\xc3\xbc"
362                                 label="\xc3\x9cml\xc3\xa4uts">
363                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
364                            </clpoint>
365                        </classification>
366                    </layer>
367              </map>              </map>
368          </session>''' % os.path.join("..", "..", "Data", "iceland",          </session>'''
369                                       "political.shp")  
370          #print written_contents          #print written_contents
371          #print "********************************************"          #print "********************************************"
372          #print expected_contents          #print expected_contents
373          self.compare_xml(written_contents, expected_contents)          self.compare_xml(written_contents, expected_contents)
374    
375            self.validate_data(written_contents)
376    
377            session.Destroy()
378    
379        def test_dbf_table(self):
380            """Test saving a session with a dbf table link"""
381            session = self.session = Session("a DBF Table session")
382            # use shapefile from the example data
383            dbffile = os.path.join(os.path.dirname(__file__),
384                                   os.pardir, "Data", "iceland", "political.dbf")
385            table = session.AddTable(DBFTable(dbffile))
386    
387            filename = self.temp_file_name("save_singletable.thuban")
388            save_session(session, filename)
389    
390            file = open(filename)
391            written_contents = file.read()
392            file.close()
393            expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
394            <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
395            <session title="a DBF Table session"
396               xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">
397                <filetable id="D1" filename="../../Data/iceland/political.dbf"
398                    filetype="DBF" title="political"/>
399            </session>'''
400    
401            self.compare_xml(written_contents, expected_contents)
402            self.validate_data(written_contents)
403    
404        def test_joined_table(self):
405            """Test saving a session with joined table"""
406            # Create a simple table to use in the join
407            dbffile = self.temp_file_name("save_joinedtable.dbf")
408            dbf = dbflib.create(dbffile)
409            dbf.add_field("RDTYPE", dbflib.FTInteger, 10, 0)
410            dbf.add_field("TEXT", dbflib.FTString, 10, 0)
411            dbf.write_record(0, {'RDTYPE': 8, "TEXT": "foo"})
412            dbf.write_record(1, {'RDTYPE': 2, "TEXT": "bar"})
413            dbf.write_record(2, {'RDTYPE': 3, "TEXT": "baz"})
414            dbf.close()
415    
416            # Create the session and a map
417            session = Session("A Joined Table session")
418            try:
419                map = Map("Test Map")
420                session.AddMap(map)
421    
422                # Add the dbf file to the session
423                dbftable = session.AddTable(DBFTable(dbffile))
424    
425                # Create a layer with the shapefile to use in the join
426                shpfile = os.path.join(os.path.abspath(os.path.dirname(__file__)),
427                                       os.pardir, "Data", "iceland",
428                                       "roads-line.shp")
429                layer = Layer("My Layer", session.OpenShapefile(shpfile))
430                map.AddLayer(layer)
431    
432                # Do the join
433                store = layer.ShapeStore()
434                #for col in store.Table().Columns():
435                #    print col.name
436                joined = TransientJoinedTable(session.TransientDB(),
437                                              store.Table(), "RDLNTYPE",
438                                              dbftable, "RDTYPE",
439                                              outer_join = True)
440                store = session.AddShapeStore(DerivedShapeStore(store, joined))
441                layer.SetShapeStore(store)
442    
443                # Save the session
444                filename = self.temp_file_name("save_joinedtable.thuban")
445                save_session(session, filename)
446    
447                # Read it back and compare
448                file = open(filename)
449                written_contents = file.read()
450                file.close()
451                expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
452                <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
453                <session title="A Joined Table session"
454                 xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">
455                    <fileshapesource filename="../../Data/iceland/roads-line.shp"
456                                     filetype="shapefile" id="D142197204"/>
457                    <filetable filename="save_joinedtable.dbf"
458                               title="save_joinedtable"
459                               filetype="DBF" id="D141881756"/>
460                    <jointable id="D142180284"
461                               title="Join of roads-line and save_joinedtable"
462                               leftcolumn="RDLNTYPE" left="D142197204"
463                               rightcolumn="RDTYPE" right="D141881756"
464                               jointype="LEFT OUTER" />
465                    <derivedshapesource id="D141915644"
466                                        table="D142180284"
467                                        shapesource="D142197204"/>
468                    <map title="Test Map">
469                        <layer title="My Layer"
470                               shapestore="D141915644" visible="true"
471                               stroke="#000000" stroke_width="1" fill="None"/>
472                    </map>
473                </session>'''
474    
475                self.compare_xml(written_contents, expected_contents)
476                self.validate_data(written_contents)
477            finally:
478                session.Destroy()
479                session = None
480    
481    
482        def test_save_postgis(self):
483            """Test saving a session with a postgis connection"""
484    
485            class NonConnection(PostGISConnection):
486                """connection class that doesn't actually connect """
487                def connect(self):
488                    pass
489    
490            class NonConnectionStore(PostGISShapeStore):
491                """Shapestore that doesn't try to access the server"""
492                def _fetch_table_information(self):
493                    # pretend that we've found a geometry column
494                    self.geometry_column = "the_geom"
495                def IDColumn(self):
496                    """Return an object with a name attribute with value 'gid'"""
497                    class dummycol:
498                        name = "gid"
499                    return dummycol
500    
501            session = Session("A PostGIS Session")
502            try:
503                dbconn = NonConnection(dbname="plugh", host="xyzzy", port="42",
504                                       user="grue")
505                session.AddDBConnection(dbconn)
506                map = Map("Test Map")
507                session.AddMap(map)
508                store = NonConnectionStore(dbconn, "roads")
509                session.AddShapeStore(store)
510                layer = Layer("Roads to Nowhere", store)
511                map.AddLayer(layer)
512    
513                # Save the session
514                filename = self.temp_file_name(self.id() + ".thuban")
515                save_session(session, filename)
516    
517                # Read it back and compare
518                file = open(filename)
519                written = file.read()
520                file.close()
521                expected = '''<?xml version="1.0" encoding="UTF-8"?>
522                <!DOCTYPE session SYSTEM "thuban-1.1.dtd">
523                <session title="A PostGIS Session"
524                 xmlns="http://thuban.intevation.org/dtds/thuban-1.1-dev.dtd">
525                    <dbconnection id="DB"
526                                  dbtype="postgis" dbname="plugh"
527                                  host="xyzzy" port="42"
528                                  user="grue"/>
529                    <dbshapesource id="roads" dbconn="DB" tablename="roads"
530                                   id_column="gid" geometry_column="the_geom"/>
531                    <map title="Test Map">
532                        <layer title="Roads to Nowhere"
533                               shapestore="roads" visible="true"
534                               stroke="#000000" stroke_width="1" fill="None"/>
535                    </map>
536                </session>'''
537                self.compare_xml(written, expected)
538                self.validate_data(written)
539            finally:
540                session.Destroy()
541    
542    
543    class MockDataStore:
544    
545        """A very simple data store that only has dependencies"""
546    
547        def __init__(self, name, *dependencies):
548            self.name = name
549            self.dependencies = dependencies
550    
551        def __repr__(self):
552            return self.name
553    
554        def Dependencies(self):
555            return self.dependencies
556    
557    
558    class TestStoreSort(unittest.TestCase):
559    
560        def check_sort(self, containers, sorted):
561            """Check whether the list of data containers is sorted"""
562            # check whether sorted is in the right order
563            seen = {}
564            for container in sorted:
565                self.failIf(id(container) in seen,
566                            "Container %r at least twice in %r" % (container,
567                                                                   sorted))
568                for dep in container.Dependencies():
569                    self.assert_(id(dep) in seen,
570                                 "Dependency %r of %r not yet seen" % (dep,
571                                                                       container))
572                seen[id(container)] = 1
573            # check whether all of containers is in sorted
574            for container in containers:
575                self.assert_(id(container) in seen,
576                             "Container %r in containers but not in sorted")
577            self.assertEquals(len(containers), len(sorted))
578    
579        def test_sort_data_stores(self):
580            """Test Thuban.Model.save.sort_data_stores"""
581            d1 = MockDataStore("d1")
582            d2 = MockDataStore("d2")
583            d3 = MockDataStore("d3", d1)
584            d4 = MockDataStore("d4", d1, d3)
585    
586            containers = [d4, d1, d2, d3]
587            self.check_sort(containers, sort_data_stores(containers))
588            containers = [d1, d3, d2, d4]
589            self.check_sort(containers, sort_data_stores(containers))
590    
591    
592    
593  if __name__ == "__main__":  if __name__ == "__main__":
594      # Fake the __file__ global because it's needed by a test      # Fake the __file__ global because it's needed by a test
595      import sys      import sys
596      __file__ = sys.argv[0]      __file__ = sys.argv[0]
597      unittest.main()      support.run_tests()

Legend:
Removed from v.494  
changed lines
  Added in v.2551

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26