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

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

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

revision 292 by bh, Fri Aug 30 09:44:12 2002 UTC revision 2036 by bh, Mon Dec 22 17:49:43 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 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.0.0.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.0.dtd">\n'
115                           '<session title="empty session">\n</session>\n')                           '<session title="empty session" '
116             'xmlns="http://thuban.intevation.org/dtds/thuban-1.0.0.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.0.dtd">
145            <session title="single map&amp;layer"
146               xmlns="http://thuban.intevation.org/dtds/thuban-1.0.0.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.0.dtd">
207            <session title="single map&amp;layer"
208               xmlns="http://thuban.intevation.org/dtds/thuban-1.0.0.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            map.AddLayer(layer)
246    
247            filename = self.temp_file_name("%s.thuban" % self.id())
248            save_session(session, filename)
249          session.Destroy()          session.Destroy()
250    
251          file = open(filename)          file = open(filename)
252          written_contents = file.read()          written_contents = file.read()
253          file.close()          file.close()
254          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>          expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
255          <!DOCTYPE session SYSTEM "thuban.dtd">          <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
256          <session title="single map&amp;layer">          <session title="single map&amp;layer"
257               xmlns="http://thuban.intevation.org/dtds/thuban-1.0.0.dtd">
258                <map title="Test Map">
259                    <rasterlayer title="My RasterLayer"
260                            filename="../../Data/iceland/island.tif"
261                            visible="true">
262                    </rasterlayer>
263                </map>
264            </session>'''
265            #print written_contents
266            #print "********************************************"
267            #print expected_contents
268            self.compare_xml(written_contents, expected_contents)
269    
270            self.validate_data(written_contents)
271    
272        def testClassifiedLayer(self):
273            """Save a session with a single map with classifications"""
274            # deliberately put an apersand in the title :)
275            session = Session("Map with Classifications")
276            proj = Projection(["zone=26", "proj=utm", "ellps=clrk66"])
277            map = Map("Test Map", projection = proj)
278            session.AddMap(map)
279            # use shapefile from the example data
280            shpfile = os.path.join(os.path.dirname(__file__),
281                                   os.pardir, "Data", "iceland", "political.shp")
282            layer = Layer("My Layer", session.OpenShapefile(shpfile))
283            map.AddLayer(layer)
284            layer2 = Layer("My Layer", layer.ShapeStore())
285            map.AddLayer(layer2)
286    
287            clazz = layer.GetClassification()
288    
289            layer.SetClassificationColumn("AREA")
290    
291            clazz.AppendGroup(ClassGroupSingleton(42, ClassGroupProperties(),
292                                                  "single"))
293            clazz.AppendGroup(ClassGroupSingleton("text", ClassGroupProperties(),
294                                                  "single-text"))
295    
296            clazz.AppendGroup(ClassGroupRange((0, 42),
297                                               ClassGroupProperties(),
298                                               "range"))
299    
300            range = ClassGroupRange(Range("[0;42]"))
301            range.SetProperties(ClassGroupProperties())
302            range.SetLabel("new-range")
303            clazz.AppendGroup(range)
304    
305    
306            clazz = layer2.GetClassification()
307            layer2.SetClassificationColumn("POPYCOUN")
308    
309            # Classification with Latin 1 text
310            clazz.AppendGroup(ClassGroupSingleton('\xe4\xf6\xfc', # ae, oe, ue
311                                                  ClassGroupProperties(),
312                                                  '\xdcml\xe4uts')) # Uemlaeuts
313    
314    
315            filename = self.temp_file_name("%s.thuban" % self.id())
316            save_session(session, filename)
317    
318            file = open(filename)
319            written_contents = file.read()
320            file.close()
321            expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
322            <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
323            <session title="Map with Classifications"
324               xmlns="http://thuban.intevation.org/dtds/thuban-1.0.0.dtd">
325                <fileshapesource id="D1"
326                    filename="../../Data/iceland/political.shp"
327                    filetype="shapefile"/>
328              <map title="Test Map">              <map title="Test Map">
329                  <projection>                  <projection name="Unknown">
330                      <parameter value="zone=26"/>                      <parameter value="zone=26"/>
331                      <parameter value="proj=utm"/>                      <parameter value="proj=utm"/>
332                      <parameter value="ellps=clrk66"/>                      <parameter value="ellps=clrk66"/>
333                  </projection>                  </projection>
334                  <layer title="My Layer" filename="%s"                  <layer title="My Layer" shapestore="D1"
335                  fill="None" stroke="#000000" stroke_width="1"/>                  fill="None" stroke="#000000" stroke_width="1" visible="true">
336                        <classification field="AREA" field_type="double">
337                            <clnull label="">
338                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
339                            </clnull>
340                            <clpoint value="42" label="single">
341                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
342                            </clpoint>
343                            <clpoint value="text" label="single-text">
344                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
345                            </clpoint>
346                            <clrange range="[0;42[" label="range">
347                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
348                            </clrange>
349                            <clrange range="[0;42]" label="new-range">
350                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
351                            </clrange>
352                        </classification>
353                    </layer>
354                    <layer title="My Layer" shapestore="D1"
355                    fill="None" stroke="#000000" stroke_width="1" visible="true">
356                        <classification field="POPYCOUN" field_type="string">
357                            <clnull label="">
358                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
359                            </clnull>
360                            <clpoint value="\xc3\xa4\xc3\xb6\xc3\xbc"
361                                 label="\xc3\x9cml\xc3\xa4uts">
362                                <cldata fill="None" stroke="#000000" stroke_width="1"/>
363                            </clpoint>
364                        </classification>
365                    </layer>
366              </map>              </map>
367          </session>''' % os.path.join("..", "..", "Data", "iceland",          </session>'''
368                                       "political.shp")  
369            #print written_contents
370            #print "********************************************"
371            #print expected_contents
372            self.compare_xml(written_contents, expected_contents)
373    
374            self.validate_data(written_contents)
375    
376            session.Destroy()
377    
378        def test_dbf_table(self):
379            """Test saving a session with a dbf table link"""
380            session = self.session = Session("a DBF Table session")
381            # use shapefile from the example data
382            dbffile = os.path.join(os.path.dirname(__file__),
383                                   os.pardir, "Data", "iceland", "political.dbf")
384            table = session.AddTable(DBFTable(dbffile))
385    
386            filename = self.temp_file_name("save_singletable.thuban")
387            save_session(session, filename)
388    
389            file = open(filename)
390            written_contents = file.read()
391            file.close()
392            expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
393            <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
394            <session title="a DBF Table session"
395               xmlns="http://thuban.intevation.org/dtds/thuban-1.0.0.dtd">
396                <filetable id="D1" filename="../../Data/iceland/political.dbf"
397                    filetype="DBF" title="political"/>
398            </session>'''
399    
400          self.compare_xml(written_contents, expected_contents)          self.compare_xml(written_contents, expected_contents)
401            self.validate_data(written_contents)
402    
403        def test_joined_table(self):
404            """Test saving a session with joined table"""
405            # Create a simple table to use in the join
406            dbffile = self.temp_file_name("save_joinedtable.dbf")
407            dbf = dbflib.create(dbffile)
408            dbf.add_field("RDTYPE", dbflib.FTInteger, 10, 0)
409            dbf.add_field("TEXT", dbflib.FTString, 10, 0)
410            dbf.write_record(0, {'RDTYPE': 8, "TEXT": "foo"})
411            dbf.write_record(1, {'RDTYPE': 2, "TEXT": "bar"})
412            dbf.write_record(2, {'RDTYPE': 3, "TEXT": "baz"})
413            dbf.close()
414    
415            # Create the session and a map
416            session = Session("A Joined Table session")
417            try:
418                map = Map("Test Map")
419                session.AddMap(map)
420    
421                # Add the dbf file to the session
422                dbftable = session.AddTable(DBFTable(dbffile))
423    
424                # Create a layer with the shapefile to use in the join
425                shpfile = os.path.join(os.path.abspath(os.path.dirname(__file__)),
426                                       os.pardir, "Data", "iceland",
427                                       "roads-line.shp")
428                layer = Layer("My Layer", session.OpenShapefile(shpfile))
429                map.AddLayer(layer)
430    
431                # Do the join
432                store = layer.ShapeStore()
433                #for col in store.Table().Columns():
434                #    print col.name
435                joined = TransientJoinedTable(session.TransientDB(),
436                                              store.Table(), "RDLNTYPE",
437                                              dbftable, "RDTYPE",
438                                              outer_join = True)
439                store = session.AddShapeStore(DerivedShapeStore(store, joined))
440                layer.SetShapeStore(store)
441    
442                # Save the session
443                filename = self.temp_file_name("save_joinedtable.thuban")
444                save_session(session, filename)
445    
446                # Read it back and compare
447                file = open(filename)
448                written_contents = file.read()
449                file.close()
450                expected_contents = '''<?xml version="1.0" encoding="UTF-8"?>
451                <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
452                <session title="A Joined Table session"
453                 xmlns="http://thuban.intevation.org/dtds/thuban-1.0.0.dtd">
454                    <fileshapesource filename="../../Data/iceland/roads-line.shp"
455                                     filetype="shapefile" id="D142197204"/>
456                    <filetable filename="save_joinedtable.dbf"
457                               title="save_joinedtable"
458                               filetype="DBF" id="D141881756"/>
459                    <jointable id="D142180284"
460                               title="Join of roads-line and save_joinedtable"
461                               leftcolumn="RDLNTYPE" left="D142197204"
462                               rightcolumn="RDTYPE" right="D141881756"
463                               jointype="LEFT OUTER" />
464                    <derivedshapesource id="D141915644"
465                                        table="D142180284"
466                                        shapesource="D142197204"/>
467                    <map title="Test Map">
468                        <layer title="My Layer"
469                               shapestore="D141915644" visible="true"
470                               stroke="#000000" stroke_width="1" fill="None"/>
471                    </map>
472                </session>'''
473    
474                self.compare_xml(written_contents, expected_contents)
475                self.validate_data(written_contents)
476            finally:
477                session.Destroy()
478                session = None
479    
480    
481        def test_save_postgis(self):
482            """Test saving a session with a postgis connection"""
483    
484            class NonConnection(PostGISConnection):
485                """connection class that doesn't actually connect """
486                def connect(self):
487                    pass
488    
489            class NonConnectionStore(PostGISShapeStore):
490                """Shapestore that doesn't try to access the server"""
491                def _fetch_table_information(self):
492                    pass
493    
494            session = Session("A PostGIS Session")
495            try:
496                dbconn = NonConnection(dbname="plugh", host="xyzzy", port="42",
497                                       user="grue")
498                session.AddDBConnection(dbconn)
499                map = Map("Test Map")
500                session.AddMap(map)
501                store = NonConnectionStore(dbconn, "roads")
502                session.AddShapeStore(store)
503                layer = Layer("Roads to Nowhere", store)
504                map.AddLayer(layer)
505    
506                # Save the session
507                filename = self.temp_file_name(self.id() + ".thuban")
508                save_session(session, filename)
509    
510                # Read it back and compare
511                file = open(filename)
512                written = file.read()
513                file.close()
514                expected = '''<?xml version="1.0" encoding="UTF-8"?>
515                <!DOCTYPE session SYSTEM "thuban-1.0.dtd">
516                <session title="A PostGIS Session"
517                 xmlns="http://thuban.intevation.org/dtds/thuban-1.0.0.dtd">
518                    <dbconnection id="DB"
519                                  dbtype="postgis" dbname="plugh"
520                                  host="xyzzy" port="42"
521                                  user="grue"/>
522                    <dbshapesource id="roads" dbconn="DB" tablename="roads"/>
523                    <map title="Test Map">
524                        <layer title="Roads to Nowhere"
525                               shapestore="roads" visible="true"
526                               stroke="#000000" stroke_width="1" fill="None"/>
527                    </map>
528                </session>'''
529                self.compare_xml(written, expected)
530                self.validate_data(written)
531            finally:
532                session.Destroy()
533    
534    
535    class MockDataStore:
536    
537        """A very simple data store that only has dependencies"""
538    
539        def __init__(self, name, *dependencies):
540            self.name = name
541            self.dependencies = dependencies
542    
543        def __repr__(self):
544            return self.name
545    
546        def Dependencies(self):
547            return self.dependencies
548    
549    
550    class TestStoreSort(unittest.TestCase):
551    
552        def check_sort(self, containers, sorted):
553            """Check whether the list of data containers is sorted"""
554            # check whether sorted is in the right order
555            seen = {}
556            for container in sorted:
557                self.failIf(id(container) in seen,
558                            "Container %r at least twice in %r" % (container,
559                                                                   sorted))
560                for dep in container.Dependencies():
561                    self.assert_(id(dep) in seen,
562                                 "Dependency %r of %r not yet seen" % (dep,
563                                                                       container))
564                seen[id(container)] = 1
565            # check whether all of containers is in sorted
566            for container in containers:
567                self.assert_(id(container) in seen,
568                             "Container %r in containers but not in sorted")
569            self.assertEquals(len(containers), len(sorted))
570    
571        def test_sort_data_stores(self):
572            """Test Thuban.Model.save.sort_data_stores"""
573            d1 = MockDataStore("d1")
574            d2 = MockDataStore("d2")
575            d3 = MockDataStore("d3", d1)
576            d4 = MockDataStore("d4", d1, d3)
577    
578            containers = [d4, d1, d2, d3]
579            self.check_sort(containers, sort_data_stores(containers))
580            containers = [d1, d3, d2, d4]
581            self.check_sort(containers, sort_data_stores(containers))
582    
583    
584    
# Line 122  if __name__ == "__main__": Line 586  if __name__ == "__main__":
586      # Fake the __file__ global because it's needed by a test      # Fake the __file__ global because it's needed by a test
587      import sys      import sys
588      __file__ = sys.argv[0]      __file__ = sys.argv[0]
589      unittest.main()      support.run_tests()

Legend:
Removed from v.292  
changed lines
  Added in v.2036

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26