/[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 755 by jonathan, Fri Apr 25 14:48:35 2003 UTC revision 1678 by bh, Thu Aug 28 13:36:23 2003 UTC
# 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, SAXNotRecognizedException  
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      #                           "\xc2\x80\xc2\x90\xc3\x82\x100")
60      # see comment at the end of Thuban/Model/load.py          eq(writer.encode(u"\xFF5E"), "\xc3\xbf5E")
61      #  
62      try:          eq(writer.encode('&"\'<>'), "&amp;&quot;&apos;&lt;&gt;")
63          parser.setFeature(xml.sax.handler.feature_validation, 0)          eq(writer.encode(unicode('&"\'<>')), "&amp;&quot;&apos;&lt;&gt;")
64          parser.setFeature(xml.sax.handler.feature_external_ges, 0)  
65          parser.setFeature(xml.sax.handler.feature_external_pes, 0)  class SaveSessionTest(unittest.TestCase, support.FileTestMixin,
66      except SAXNotRecognizedException:                        xmlsupport.ValidationTest):
67          pass  
68        dtd = "http://thuban.intevation.org/dtds/thuban-0.9.dtd"
69      inpsrc = xml.sax.InputSource()      thubanids = [((dtd, n), (None, "id")) for n in
70      inpsrc.setByteStream(StringIO(data))                   ["fileshapesource", "filetable", "jointable",
71      parser.parse(inpsrc)                    "derivedshapesource", "dbshapesource", "dbconnection"]]
72        thubanidrefs = [((dtd, n), (None, m)) for n, m in
73      return handler.eventlist                      [("layer", "shapestore"),
74                         ("jointable", "left"),
75  class SaveSessionTest(unittest.TestCase, support.FileTestMixin):                       ("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 87  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-0.9.dtd">\n'
115                           '<session title="empty session">\n</session>\n')                           '<session title="empty session" '
116             'xmlns="http://thuban.intevation.org/dtds/thuban-0.9.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"""
# Line 105  class SaveSessionTest(unittest.TestCase, Line 133  class SaveSessionTest(unittest.TestCase,
133    
134          filename = self.temp_file_name("save_singlemap.thuban")          filename = self.temp_file_name("save_singlemap.thuban")
135          save_session(session, filename)          save_session(session, filename)
         session.Destroy()  
136    
137          file = open(filename)          file = open(filename)
138          written_contents = file.read()          written_contents = file.read()
139          file.close()          file.close()
140          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>          expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
141          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
142          <session title="single map&amp;layer">          <session title="single map&amp;layer"
143               xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
144                <fileshapesource id="D1" filename="%s" filetype="shapefile"/>
145              <map title="Test Map">              <map title="Test Map">
146                  <projection name="Unknown">                  <projection name="Unknown">
147                      <parameter value="zone=26"/>                      <parameter value="zone=26"/>
148                      <parameter value="proj=utm"/>                      <parameter value="proj=utm"/>
149                      <parameter value="ellps=clrk66"/>                      <parameter value="ellps=clrk66"/>
150                  </projection>                  </projection>
151                  <layer title="My Layer" filename="%s"                  <layer title="My Layer" shapestore="D1"
152                  fill="None" stroke="#000000" stroke_width="1"/>                  fill="None" stroke="#000000" stroke_width="1" visible="%s"/>
153              </map>              </map>
154          </session>''' % os.path.join("..", "..", "Data", "iceland",          </session>'''
155                                       "political.shp")  
156          #print written_contents          expected_contents = expected_template % \
157          #print "********************************************"              (os.path.join("..", "..", "Data", "iceland", "political.shp"),
158          #print expected_contents               "true")
159    
160          self.compare_xml(written_contents, expected_contents)          self.compare_xml(written_contents, expected_contents)
161    
162            self.validate_data(written_contents)
163    
164            layer.SetVisible(False)
165            save_session(session, filename)
166    
167            file = open(filename)
168            written_contents = file.read()
169            file.close()
170            expected_contents = expected_template % \
171                (os.path.join("..", "..", "Data", "iceland", "political.shp"),
172                 "false")
173            self.compare_xml(written_contents, expected_contents)
174            self.validate_data(written_contents)
175    
176            session.Destroy()
177    
178      def testLayerProjection(self):      def testLayerProjection(self):
179            """Test saving layers with projections"""
180          # deliberately put an apersand in the title :)          # deliberately put an apersand in the title :)
181          session = Session("single map&layer")          session = self.session = Session("single map&layer")
182          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])          proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
183          map = Map("Test Map", projection = proj)          map = Map("Test Map", projection = proj)
184          session.AddMap(map)          session.AddMap(map)
# Line 143  class SaveSessionTest(unittest.TestCase, Line 190  class SaveSessionTest(unittest.TestCase,
190          layer.SetProjection(proj)          layer.SetProjection(proj)
191          map.AddLayer(layer)          map.AddLayer(layer)
192    
193          filename = self.temp_file_name("save_singlemap.thuban")          filename = self.temp_file_name("save_layerproj.thuban")
194          save_session(session, filename)          save_session(session, filename)
         session.Destroy()  
195    
196          file = open(filename)          file = open(filename)
197          written_contents = file.read()          written_contents = file.read()
198          file.close()          file.close()
199          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
200          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
201          <session title="single map&amp;layer">          <session title="single map&amp;layer"
202               xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
203                <fileshapesource id="D1" filename="%s" filetype="shapefile"/>
204              <map title="Test Map">              <map title="Test Map">
205                  <projection name="Unknown">                  <projection name="Unknown">
206                      <parameter value="zone=26"/>                      <parameter value="zone=26"/>
207                      <parameter value="proj=utm"/>                      <parameter value="proj=utm"/>
208                      <parameter value="ellps=clrk66"/>                      <parameter value="ellps=clrk66"/>
209                  </projection>                  </projection>
210                  <layer title="My Layer" filename="%s"                  <layer title="My Layer" shapestore="D1"
211                  fill="None" stroke="#000000" stroke_width="1">                  fill="None" stroke="#000000" stroke_width="1" visible="true">
212                      <projection name="Layer Projection">                      <projection name="Layer Projection">
213                          <parameter value="proj=lcc"/>                          <parameter value="proj=lcc"/>
214                          <parameter value="ellps=clrk66"/>                          <parameter value="ellps=clrk66"/>
# Line 174  class SaveSessionTest(unittest.TestCase, Line 222  class SaveSessionTest(unittest.TestCase,
222          #print expected_contents          #print expected_contents
223          self.compare_xml(written_contents, expected_contents)          self.compare_xml(written_contents, expected_contents)
224    
225                    self.validate_data(written_contents)
226    
227        def testRasterLayer(self):
228            # deliberately put an apersand in the title :)
229            session = Session("single map&layer")
230            map = Map("Test Map")
231            session.AddMap(map)
232            # use shapefile from the example data
233            imgfile = os.path.join(os.path.dirname(__file__),
234                                   os.pardir, "Data", "iceland", "island.tif")
235            layer = RasterLayer("My RasterLayer", imgfile)
236            map.AddLayer(layer)
237    
238            filename = self.temp_file_name("%s.thuban" % self.id())
239            save_session(session, filename)
240            session.Destroy()
241    
242            file = open(filename)
243            written_contents = file.read()
244            file.close()
245            expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
246            <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
247            <session title="single map&amp;layer"
248               xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
249                <map title="Test Map">
250                    <rasterlayer title="My RasterLayer" filename="%s"
251                                 visible="true">
252                    </rasterlayer>
253                </map>
254            </session>''' % os.path.join(os.pardir, os.pardir, "Data", "iceland",
255                                         "island.tif")
256            #print written_contents
257            #print "********************************************"
258            #print expected_contents
259            self.compare_xml(written_contents, expected_contents)
260    
261            self.validate_data(written_contents)
262    
263        def testClassifiedLayer(self):
264            """Save a session with a single map with classifications"""
265            # deliberately put an apersand in the title :)
266            session = Session("Map with Classifications")
267            proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
268            map = Map("Test Map", projection = proj)
269            session.AddMap(map)
270            # use shapefile from the example data
271            shpfile = os.path.join(os.path.dirname(__file__),
272                                   os.pardir, "Data", "iceland", "political.shp")
273            layer = Layer("My Layer", session.OpenShapefile(shpfile))
274            map.AddLayer(layer)
275            layer2 = Layer("My Layer", layer.ShapeStore())
276            map.AddLayer(layer2)
277    
278            clazz = layer.GetClassification()
279    
280            layer.SetClassificationColumn("AREA")
281    
282            clazz.AppendGroup(ClassGroupSingleton(42, ClassGroupProperties(),
283                                                  "single"))
284            clazz.AppendGroup(ClassGroupSingleton("text", ClassGroupProperties(),
285                                                  "single-text"))
286    
287            clazz.AppendGroup(ClassGroupRange((0, 42),
288                                               ClassGroupProperties(),
289                                               "range"))
290    
291            range = ClassGroupRange(Range("[0;42]"))
292            range.SetProperties(ClassGroupProperties())
293            range.SetLabel("new-range")
294            clazz.AppendGroup(range)
295    
296    
297            clazz = layer2.GetClassification()
298            layer2.SetClassificationColumn("POPYCOUN")
299    
300            # Classification with Latin 1 text
301            clazz.AppendGroup(ClassGroupSingleton('\xe4\xf6\xfc', # ae, oe, ue
302                                                  ClassGroupProperties(),
303                                                  '\xdcml\xe4uts')) # Uemlaeuts
304    
305    
306            filename = self.temp_file_name("%s.thuban" % self.id())
307            save_session(session, filename)
308    
309            file = open(filename)
310            written_contents = file.read()
311            file.close()
312            expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
313            <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
314            <session title="Map with Classifications"
315               xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
316                <fileshapesource id="D1" filename="%s" filetype="shapefile"/>
317                <map title="Test Map">
318                    <projection name="Unknown">
319                        <parameter value="zone=26"/>
320                        <parameter value="proj=utm"/>
321                        <parameter value="ellps=clrk66"/>
322                    </projection>
323                    <layer title="My Layer" shapestore="D1"
324                    fill="None" stroke="#000000" stroke_width="1" visible="%s">
325                        <classification field="AREA" field_type="double">
326                            <clnull label="">
327                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
328                            </clnull>
329                            <clpoint value="42" label="single">
330                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
331                            </clpoint>
332                            <clpoint value="text" label="single-text">
333                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
334                            </clpoint>
335                            <clrange range="[0;42[" label="range">
336                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
337                            </clrange>
338                            <clrange range="[0;42]" label="new-range">
339                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
340                            </clrange>
341                        </classification>
342                    </layer>
343                    <layer title="My Layer" shapestore="D1"
344                    fill="None" stroke="#000000" stroke_width="1" visible="true">
345                        <classification field="POPYCOUN" field_type="string">
346                            <clnull label="">
347                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
348                            </clnull>
349                            <clpoint value="\xc3\xa4\xc3\xb6\xc3\xbc"
350                                 label="\xc3\x9cml\xc3\xa4uts">
351                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
352                            </clpoint>
353                        </classification>
354                    </layer>
355                </map>
356            </session>'''
357    
358            expected_contents = expected_template % \
359                (os.path.join("..", "..", "Data", "iceland", "political.shp"),
360                 "true")
361    
362            #print written_contents
363            #print "********************************************"
364            #print expected_contents
365            self.compare_xml(written_contents, expected_contents)
366    
367            self.validate_data(written_contents)
368    
369            session.Destroy()
370    
371        def test_dbf_table(self):
372            """Test saving a session with a dbf table link"""
373            session = self.session = Session("a DBF Table session")
374            # use shapefile from the example data
375            dbffile = os.path.join(os.path.dirname(__file__),
376                                   os.pardir, "Data", "iceland", "political.dbf")
377            table = session.AddTable(DBFTable(dbffile))
378    
379            filename = self.temp_file_name("save_singletable.thuban")
380            save_session(session, filename)
381    
382            file = open(filename)
383            written_contents = file.read()
384            file.close()
385            expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
386            <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
387            <session title="a DBF Table session"
388               xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
389                <filetable id="D1" filename="%s" filetype="DBF" title="political"/>
390            </session>'''
391    
392            expected_contents = (expected_template
393                                 % os.path.join(os.pardir, os.pardir, "Data",
394                                                "iceland", "political.dbf"))
395            self.compare_xml(written_contents, expected_contents)
396            self.validate_data(written_contents)
397    
398        def test_joined_table(self):
399            """Test saving a session with joined table"""
400            # Create a simple table to use in the join
401            dbffile = self.temp_file_name("save_joinedtable.dbf")
402            dbf = dbflib.create(dbffile)
403            dbf.add_field("RDTYPE", dbflib.FTInteger, 10, 0)
404            dbf.add_field("TEXT", dbflib.FTString, 10, 0)
405            dbf.write_record(0, {'RDTYPE': 8, "TEXT": "foo"})
406            dbf.write_record(1, {'RDTYPE': 2, "TEXT": "bar"})
407            dbf.write_record(2, {'RDTYPE': 3, "TEXT": "baz"})
408            dbf.close()
409    
410            # Create the session and a map
411            session = Session("A Joined Table session")
412            try:
413                map = Map("Test Map")
414                session.AddMap(map)
415    
416                # Add the dbf file to the session
417                dbftable = session.AddTable(DBFTable(dbffile))
418    
419                # Create a layer with the shapefile to use in the join
420                shpfile = os.path.join(os.path.abspath(os.path.dirname(__file__)),
421                                       os.pardir, "Data", "iceland",
422                                       "roads-line.shp")
423                layer = Layer("My Layer", session.OpenShapefile(shpfile))
424                map.AddLayer(layer)
425    
426                # Do the join
427                store = layer.ShapeStore()
428                #for col in store.Table().Columns():
429                #    print col.name
430                joined = TransientJoinedTable(session.TransientDB(),
431                                              store.Table(), "RDLNTYPE",
432                                              dbftable, "RDTYPE",
433                                              outer_join = True)
434                store = session.AddShapeStore(DerivedShapeStore(store, joined))
435                layer.SetShapeStore(store)
436    
437                # Save the session
438                filename = self.temp_file_name("save_joinedtable.thuban")
439                save_session(session, filename)
440    
441                # Read it back and compare
442                file = open(filename)
443                written_contents = file.read()
444                file.close()
445                expected_template = '''<?xml version="1.0" encoding="UTF-8"?>
446                <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
447                <session title="A Joined Table session"
448                 xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
449                    <fileshapesource filename="%(shpfile)s"
450                                     filetype="shapefile" id="D142197204"/>
451                    <filetable filename="%(dbffile)s"
452                               title="save_joinedtable"
453                               filetype="DBF" id="D141881756"/>
454                    <jointable id="D142180284"
455                               title="Join of roads-line and save_joinedtable"
456                               leftcolumn="RDLNTYPE" left="D142197204"
457                               rightcolumn="RDTYPE" right="D141881756"
458                               jointype="LEFT OUTER" />
459                    <derivedshapesource id="D141915644"
460                                        table="D142180284"
461                                        shapesource="D142197204"/>
462                    <map title="Test Map">
463                        <layer title="My Layer"
464                               shapestore="D141915644" visible="true"
465                               stroke="#000000" stroke_width="1" fill="None"/>
466                    </map>
467                </session>'''
468    
469                expected_contents = expected_template % {
470                    "dbffile": relative_filename(self.temp_dir(), dbffile),
471                    "shpfile": relative_filename(self.temp_dir(), shpfile)
472                    }
473                self.compare_xml(written_contents, expected_contents)
474                self.validate_data(written_contents)
475            finally:
476                session.Destroy()
477                session = None
478    
479    
480        def test_save_postgis(self):
481            """Test saving a session with a postgis connection"""
482    
483            class NonConnection(PostGISConnection):
484                """connection class that doesn't actually connect """
485                def connect(self):
486                    pass
487    
488            class NonConnectionStore(PostGISShapeStore):
489                """Shapestore that doesn't try to access the server"""
490                def _fetch_table_information(self):
491                    pass
492    
493            session = Session("A PostGIS Session")
494            try:
495                dbconn = NonConnection(dbname="plugh", host="xyzzy", port="42",
496                                       user="grue")
497                session.AddDBConnection(dbconn)
498                map = Map("Test Map")
499                session.AddMap(map)
500                store = NonConnectionStore(dbconn, "roads")
501                session.AddShapeStore(store)
502                layer = Layer("Roads to Nowhere", store)
503                map.AddLayer(layer)
504    
505                # Save the session
506                filename = self.temp_file_name(self.id() + ".thuban")
507                save_session(session, filename)
508    
509                # Read it back and compare
510                file = open(filename)
511                written = file.read()
512                file.close()
513                expected = '''<?xml version="1.0" encoding="UTF-8"?>
514                <!DOCTYPE session SYSTEM "thuban-0.9.dtd">
515                <session title="A PostGIS Session"
516                 xmlns="http://thuban.intevation.org/dtds/thuban-0.9.dtd">
517                    <dbconnection id="DB"
518                                  dbtype="postgis" dbname="plugh"
519                                  host="xyzzy" port="42"
520                                  user="grue"/>
521                    <dbshapesource id="roads" dbconn="DB" tablename="roads"/>
522                    <map title="Test Map">
523                        <layer title="Roads to Nowhere"
524                               shapestore="roads" visible="true"
525                               stroke="#000000" stroke_width="1" fill="None"/>
526                    </map>
527                </session>'''
528                self.compare_xml(written, expected)
529                self.validate_data(written)
530            finally:
531                session.Destroy()
532    
533    
534    class MockDataStore:
535    
536        """A very simple data store that only has dependencies"""
537    
538        def __init__(self, name, *dependencies):
539            self.name = name
540            self.dependencies = dependencies
541    
542        def __repr__(self):
543            return self.name
544    
545        def Dependencies(self):
546            return self.dependencies
547    
548    
549    class TestStoreSort(unittest.TestCase):
550    
551        def check_sort(self, containers, sorted):
552            """Check whether the list of data containers is sorted"""
553            # check whether sorted is in the right order
554            seen = {}
555            for container in sorted:
556                self.failIf(id(container) in seen,
557                            "Container %r at least twice in %r" % (container,
558                                                                   sorted))
559                for dep in container.Dependencies():
560                    self.assert_(id(dep) in seen,
561                                 "Dependency %r of %r not yet seen" % (dep,
562                                                                       container))
563                seen[id(container)] = 1
564            # check whether all of containers is in sorted
565            for container in containers:
566                self.assert_(id(container) in seen,
567                             "Container %r in containers but not in sorted")
568            self.assertEquals(len(containers), len(sorted))
569    
570        def test_sort_data_stores(self):
571            """Test Thuban.Model.save.sort_data_stores"""
572            d1 = MockDataStore("d1")
573            d2 = MockDataStore("d2")
574            d3 = MockDataStore("d3", d1)
575            d4 = MockDataStore("d4", d1, d3)
576    
577            containers = [d4, d1, d2, d3]
578            self.check_sort(containers, sort_data_stores(containers))
579            containers = [d1, d3, d2, d4]
580            self.check_sort(containers, sort_data_stores(containers))
581    
582    
583    

Legend:
Removed from v.755  
changed lines
  Added in v.1678

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26