Started implementing SAT solver in Python
[zeroinstall.git] / tests / testsolver.py
blob15ff73342ec43682b46dcc2a45e22d8a8b13ec0e
1 #!/usr/bin/env python
2 from basetest import BaseTest
3 import sys, os
4 import unittest
6 sys.path.insert(0, '..')
7 from zeroinstall.zerostore import Stores
8 from zeroinstall.injector import solver, reader, arch, model
9 from zeroinstall.injector.iface_cache import iface_cache
11 import logging
12 logger = logging.getLogger()
13 #logger.setLevel(logging.DEBUG)
15 class TestSolver(BaseTest):
16 def testSimple(self):
17 s = solver.DefaultSolver(model.network_full, iface_cache, Stores())
19 foo = iface_cache.get_interface('http://foo/Binary.xml')
20 reader.update(foo, 'Binary.xml')
21 foo_src = iface_cache.get_interface('http://foo/Source.xml')
22 reader.update(foo_src, 'Source.xml')
23 compiler = iface_cache.get_interface('http://foo/Compiler.xml')
24 reader.update(compiler, 'Compiler.xml')
26 binary_arch = arch.Architecture({None: 1}, {None: 1})
27 assert str(binary_arch).startswith("<Arch")
28 s.solve('http://foo/Binary.xml', binary_arch)
30 assert s.ready
31 assert s.feeds_used == set([foo.uri]), s.feeds_used
32 assert s.selections[foo].id == 'sha1=123'
34 # Now ask for source instead
35 s.solve('http://foo/Binary.xml',
36 arch.SourceArchitecture(binary_arch))
37 assert s.ready
38 assert s.feeds_used == set([foo.uri, foo_src.uri, compiler.uri]), s.feeds_used
39 assert s.selections[foo].id == 'sha1=234' # The source
40 assert s.selections[compiler].id == 'sha1=345' # A binary needed to compile it
42 assert not s.details
44 def testDetails(self):
45 s = solver.DefaultSolver(model.network_full, iface_cache, Stores())
47 foo = iface_cache.get_interface('http://foo/Binary.xml')
48 reader.update(foo, 'Binary.xml')
49 foo_src = iface_cache.get_interface('http://foo/Source.xml')
50 reader.update(foo_src, 'Source.xml')
51 compiler = iface_cache.get_interface('http://foo/Compiler.xml')
52 reader.update(compiler, 'Compiler.xml')
54 binary_arch = arch.Architecture({None: 1}, {None: 1})
55 s.record_details = True
56 s.solve('http://foo/Binary.xml', arch.SourceArchitecture(binary_arch))
57 assert s.ready
59 assert len(s.details) == 2
60 self.assertEquals([(foo_src._main_feed.implementations['sha1=234'], None),
61 (foo._main_feed.implementations['sha1=123'], 'Unsupported machine type')],
62 sorted(s.details[foo]))
63 assert s.details[compiler] == [(compiler._main_feed.implementations['sha1=345'], None)]
65 def testRecursive(self):
66 s = solver.DefaultSolver(model.network_full, iface_cache, Stores())
68 foo = iface_cache.get_interface('http://foo/Recursive.xml')
69 reader.update(foo, 'Recursive.xml')
71 binary_arch = arch.Architecture({None: 1}, {None: 1})
72 s.record_details = True
73 s.solve('http://foo/Recursive.xml', binary_arch)
74 assert s.ready
76 assert len(s.details) == 1
77 assert s.details[foo] == [(foo._main_feed.implementations['sha1=abc'], None)]
79 def testMultiArch(self):
80 s = solver.DefaultSolver(model.network_full, iface_cache, Stores())
82 foo = iface_cache.get_interface('http://foo/MultiArch.xml')
83 reader.update(foo, 'MultiArch.xml')
84 lib = iface_cache.get_interface('http://foo/MultiArchLib.xml')
85 reader.update(lib, 'MultiArchLib.xml')
87 # On an i686 system we can only use the i486 implementation
89 binary_arch = arch.get_architecture('Linux', 'i686')
90 s.solve('http://foo/MultiArch.xml', binary_arch)
91 assert s.ready
92 assert s.selections[foo].machine == 'i486'
93 assert s.selections[lib].machine == 'i486'
95 # On an 64 bit system we could use either, but we prefer the 64
96 # bit implementation. The i486 version of the library is newer,
97 # but we must pick one that is compatible with the main binary.
99 binary_arch = arch.get_architecture('Linux', 'x86_64')
100 s.solve('http://foo/MultiArch.xml', binary_arch)
101 assert s.ready
102 assert s.selections[foo].machine == 'x86_64'
103 assert s.selections[lib].machine == 'x86_64'
105 def testArch(self):
106 host_arch = arch.get_host_architecture()
107 host_arch2 = arch.get_architecture(None, None)
108 self.assertEquals(host_arch.os_ranks, host_arch2.os_ranks)
109 self.assertEquals(host_arch.machine_ranks, host_arch2.machine_ranks)
111 other = arch.get_architecture('FooBar', 'i486')
112 self.assertEquals(2, len(other.os_ranks))
114 assert 'FooBar' in other.os_ranks
115 assert None in other.os_ranks
116 assert 'i486' in other.machine_ranks
117 assert 'ppc' not in other.machine_ranks
119 def testRanking(self):
120 s = solver.DefaultSolver(model.network_full, iface_cache, Stores())
121 ranking = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'Ranking.xml')
122 iface = iface_cache.get_interface(ranking)
124 binary_arch = arch.get_architecture('Linux', 'x86_64')
125 selected = []
126 while True:
127 s.solve(ranking, binary_arch)
128 if not s.ready:
129 break
130 impl = s.selections[iface]
131 selected.append(impl.get_version() + ' ' + impl.arch)
132 impl.arch = 'Foo-odd' # prevent reselection
133 self.assertEquals([
134 '0.2 Linux-i386', # poor arch, but newest version
135 '0.1 Linux-x86_64', # 64-bit is best match for host arch
136 '0.1 Linux-i686', '0.1 Linux-i586', '0.1 Linux-i486'], # ordering of x86 versions
137 selected)
139 suite = unittest.makeSuite(TestSolver)
140 if __name__ == '__main__':
141 sys.argv.append('-v')
142 unittest.main()