Large-scale API cleanup
[zeroinstall/zeroinstall-afb.git] / tests / testsolver.py
blobad962ebf2e70b851a27a461d77cfa792ae3591d3
1 #!/usr/bin/env python
2 from basetest import BaseTest
3 import sys, os, locale
4 import unittest
6 sys.path.insert(0, '..')
7 from zeroinstall.injector import solver, arch
9 import logging
10 logger = logging.getLogger()
11 #logger.setLevel(logging.DEBUG)
13 class TestSolver(BaseTest):
14 def testSimple(self):
15 iface_cache = self.config.iface_cache
16 s = solver.DefaultSolver(self.config)
18 foo = iface_cache.get_interface('http://foo/Binary.xml')
19 self.import_feed(foo.uri, 'Binary.xml')
20 foo_src = iface_cache.get_interface('http://foo/Source.xml')
21 self.import_feed(foo_src.uri, 'Source.xml')
22 compiler = iface_cache.get_interface('http://foo/Compiler.xml')
23 self.import_feed(compiler.uri, 'Compiler.xml')
25 binary_arch = arch.Architecture({None: 1}, {None: 1})
26 assert str(binary_arch).startswith("<Arch")
27 s.solve('http://foo/Binary.xml', binary_arch)
29 assert s.ready
30 assert s.feeds_used == set([foo.uri]), s.feeds_used
31 assert s.selections[foo].id == 'sha1=123'
33 # Now ask for source instead
34 s.solve('http://foo/Binary.xml',
35 arch.SourceArchitecture(binary_arch),
36 command_name = 'compile')
37 assert s.ready, s.get_failure_reason()
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 iface_cache = self.config.iface_cache
46 s = solver.DefaultSolver(self.config)
48 foo_binary_uri = 'http://foo/Binary.xml'
49 foo = iface_cache.get_interface(foo_binary_uri)
50 self.import_feed(foo_binary_uri, 'Binary.xml')
51 foo_src = iface_cache.get_interface('http://foo/Source.xml')
52 self.import_feed(foo_src.uri, 'Source.xml')
53 compiler = iface_cache.get_interface('http://foo/Compiler.xml')
54 self.import_feed(compiler.uri, 'Compiler.xml')
56 binary_arch = arch.Architecture({None: 1}, {None: 1})
57 s.record_details = True
58 s.solve('http://foo/Binary.xml', arch.SourceArchitecture(binary_arch), command_name = 'compile')
59 assert s.ready, s.get_failure_reason()
61 foo_src_impls = iface_cache.get_feed(foo_src.uri).implementations
62 foo_impls = iface_cache.get_feed(foo.uri).implementations
63 compiler_impls = iface_cache.get_feed(compiler.uri).implementations
65 assert len(s.details) == 2
66 self.assertEquals([(foo_src_impls['sha1=234'], None),
67 (foo_impls['sha1=123'], 'Unsupported machine type')],
68 sorted(s.details[foo]))
69 assert s.details[compiler] == [(compiler_impls['sha1=345'], None)]
71 def testRecursive(self):
72 iface_cache = self.config.iface_cache
73 s = solver.DefaultSolver(self.config)
75 foo = iface_cache.get_interface('http://foo/Recursive.xml')
76 self.import_feed(foo.uri, 'Recursive.xml')
78 binary_arch = arch.Architecture({None: 1}, {None: 1})
79 s.record_details = True
80 s.solve('http://foo/Recursive.xml', binary_arch)
81 assert s.ready
83 foo_impls = iface_cache.get_feed(foo.uri).implementations
85 assert len(s.details) == 1
86 assert s.details[foo] == [(foo_impls['sha1=abc'], None)]
88 def testMultiArch(self):
89 iface_cache = self.config.iface_cache
90 s = solver.DefaultSolver(self.config)
92 foo = iface_cache.get_interface('http://foo/MultiArch.xml')
93 self.import_feed(foo.uri, 'MultiArch.xml')
94 lib = iface_cache.get_interface('http://foo/MultiArchLib.xml')
95 self.import_feed(lib.uri, 'MultiArchLib.xml')
97 # On an i686 system we can only use the i486 implementation
99 binary_arch = arch.get_architecture('Linux', 'i686')
100 s.solve('http://foo/MultiArch.xml', binary_arch)
101 assert s.ready
102 assert s.selections[foo].machine == 'i486'
103 assert s.selections[lib].machine == 'i486'
105 # On an 64 bit system we could use either, but we prefer the 64
106 # bit implementation. The i486 version of the library is newer,
107 # but we must pick one that is compatible with the main binary.
109 binary_arch = arch.get_architecture('Linux', 'x86_64')
110 s.solve('http://foo/MultiArch.xml', binary_arch)
111 assert s.ready
112 assert s.selections[foo].machine == 'x86_64'
113 assert s.selections[lib].machine == 'x86_64'
115 def testArch(self):
116 host_arch = arch.get_host_architecture()
117 host_arch2 = arch.get_architecture(None, None)
118 self.assertEquals(host_arch.os_ranks, host_arch2.os_ranks)
119 self.assertEquals(host_arch.machine_ranks, host_arch2.machine_ranks)
121 other = arch.get_architecture('FooBar', 'i486')
122 self.assertEquals(2, len(other.os_ranks))
124 assert 'FooBar' in other.os_ranks
125 assert None in other.os_ranks
126 assert 'i486' in other.machine_ranks
127 assert 'ppc' not in other.machine_ranks
129 def testRanking(self):
130 iface_cache = self.config.iface_cache
131 s = solver.DefaultSolver(self.config)
132 ranking = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'Ranking.xml')
133 iface = iface_cache.get_interface(ranking)
135 binary_arch = arch.get_architecture('Linux', 'x86_64')
136 selected = []
137 while True:
138 s.solve(ranking, binary_arch)
139 if not s.ready:
140 break
141 impl = s.selections[iface]
142 selected.append(impl.get_version() + ' ' + impl.arch)
143 impl.arch = 'Foo-odd' # prevent reselection
144 self.assertEquals([
145 '0.2 Linux-i386', # poor arch, but newest version
146 '0.1 Linux-x86_64', # 64-bit is best match for host arch
147 '0.1 Linux-i686', '0.1 Linux-i586', '0.1 Linux-i486'], # ordering of x86 versions
148 selected)
150 def testLangs(self):
151 iface_cache = self.config.iface_cache
152 try:
153 locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
155 s = solver.DefaultSolver(self.config)
156 iface = iface_cache.get_interface('http://foo/Langs.xml')
157 self.import_feed(iface.uri, 'Langs.xml')
159 # 1 is the oldest, but the only one in our language
160 binary_arch = arch.get_architecture(None, 'arch_1')
161 s.solve('http://foo/Langs.xml', binary_arch)
162 assert s.ready
163 self.assertEquals('sha1=1', s.selections[iface].id)
165 # 6 is the newest, and close enough, even though not
166 # quite the right locale
167 binary_arch = arch.get_architecture(None, 'arch_2')
168 s.solve('http://foo/Langs.xml', binary_arch)
169 assert s.ready
170 self.assertEquals('sha1=6', s.selections[iface].id)
172 # 9 is the newest, although 7 is a closer match
173 binary_arch = arch.get_architecture(None, 'arch_3')
174 s.solve('http://foo/Langs.xml', binary_arch)
175 assert s.ready
176 self.assertEquals('sha1=9', s.selections[iface].id)
178 # 11 is the newest we understand
179 binary_arch = arch.get_architecture(None, 'arch_4')
180 s.solve('http://foo/Langs.xml', binary_arch)
181 assert s.ready
182 self.assertEquals('sha1=11', s.selections[iface].id)
184 # 13 is the newest we understand
185 binary_arch = arch.get_architecture(None, 'arch_5')
186 s.solve('http://foo/Langs.xml', binary_arch)
187 assert s.ready
188 self.assertEquals('sha1=13', s.selections[iface].id)
190 def check(target_arch, langs, expected):
191 s.langs = langs
192 binary_arch = arch.get_architecture(None, target_arch)
193 s.solve('http://foo/Langs.xml', binary_arch)
194 assert s.ready
195 self.assertEquals(expected, s.selections[iface].id)
197 # We don't understand any, so pick the newest
198 check('arch_2', ['es_ES'], 'sha1=6')
200 # These two have the same version number. Choose the
201 # one most appropriate to our country
202 check('arch_6', ['zh_CN'], 'sha1=15')
203 check('arch_6', ['zh_TW'], 'sha1=16')
205 # Same, but one doesn't have a country code
206 check('arch_7', ['bn'], 'sha1=17')
207 check('arch_7', ['bn_IN'], 'sha1=18')
208 finally:
209 locale.setlocale(locale.LC_ALL, '')
211 if __name__ == '__main__':
212 unittest.main()