Added '0install config' sub-command
[zeroinstall.git] / tests / testsolver.py
blob5ab6af859bfee4714e01c90e30cccdf0ab411e46
1 #!/usr/bin/env python
2 from basetest import BaseTest
3 import sys, os, locale
4 import ConfigParser
5 import unittest
7 sys.path.insert(0, '..')
8 from zeroinstall.zerostore import Stores
9 from zeroinstall.injector import solver, reader, arch, model
10 from zeroinstall.injector.iface_cache import iface_cache
12 import logging
13 logger = logging.getLogger()
14 #logger.setLevel(logging.DEBUG)
16 test_config = ConfigParser.ConfigParser()
17 test_config.add_section('global')
18 test_config.set('global', 'help_with_testing', 'False')
19 test_config.set('global', 'freshness', str(60 * 60 * 24 * 30)) # One month
20 test_config.set('global', 'network_use', 'full')
22 class TestSolver(BaseTest):
23 def testSimple(self):
24 s = solver.DefaultSolver(test_config, iface_cache, Stores())
26 foo = iface_cache.get_interface('http://foo/Binary.xml')
27 reader.update(foo, 'Binary.xml')
28 foo_src = iface_cache.get_interface('http://foo/Source.xml')
29 reader.update(foo_src, 'Source.xml')
30 compiler = iface_cache.get_interface('http://foo/Compiler.xml')
31 reader.update(compiler, 'Compiler.xml')
33 binary_arch = arch.Architecture({None: 1}, {None: 1})
34 assert str(binary_arch).startswith("<Arch")
35 s.solve('http://foo/Binary.xml', binary_arch)
37 assert s.ready
38 assert s.feeds_used == set([foo.uri]), s.feeds_used
39 assert s.selections[foo].id == 'sha1=123'
41 # Now ask for source instead
42 s.solve('http://foo/Binary.xml',
43 arch.SourceArchitecture(binary_arch),
44 command_name = 'compile')
45 assert s.ready, s.get_failure_reason()
46 assert s.feeds_used == set([foo.uri, foo_src.uri, compiler.uri]), s.feeds_used
47 assert s.selections[foo].id == 'sha1=234' # The source
48 assert s.selections[compiler].id == 'sha1=345' # A binary needed to compile it
50 assert not s.details
52 def testDetails(self):
53 s = solver.DefaultSolver(test_config, iface_cache, Stores())
55 foo = iface_cache.get_interface('http://foo/Binary.xml')
56 reader.update(foo, 'Binary.xml')
57 foo_src = iface_cache.get_interface('http://foo/Source.xml')
58 reader.update(foo_src, 'Source.xml')
59 compiler = iface_cache.get_interface('http://foo/Compiler.xml')
60 reader.update(compiler, 'Compiler.xml')
62 binary_arch = arch.Architecture({None: 1}, {None: 1})
63 s.record_details = True
64 s.solve('http://foo/Binary.xml', arch.SourceArchitecture(binary_arch), command_name = 'compile')
65 assert s.ready, s.get_failure_reason()
67 foo_src_impls = iface_cache.get_feed(foo_src.uri).implementations
68 foo_impls = iface_cache.get_feed(foo.uri).implementations
69 compiler_impls = iface_cache.get_feed(compiler.uri).implementations
71 assert len(s.details) == 2
72 self.assertEquals([(foo_src_impls['sha1=234'], None),
73 (foo_impls['sha1=123'], 'Unsupported machine type')],
74 sorted(s.details[foo]))
75 assert s.details[compiler] == [(compiler_impls['sha1=345'], None)]
77 def testRecursive(self):
78 s = solver.DefaultSolver(test_config, iface_cache, Stores())
80 foo = iface_cache.get_interface('http://foo/Recursive.xml')
81 reader.update(foo, 'Recursive.xml')
83 binary_arch = arch.Architecture({None: 1}, {None: 1})
84 s.record_details = True
85 s.solve('http://foo/Recursive.xml', binary_arch)
86 assert s.ready
88 foo_impls = iface_cache.get_feed(foo.uri).implementations
90 assert len(s.details) == 1
91 assert s.details[foo] == [(foo_impls['sha1=abc'], None)]
93 def testMultiArch(self):
94 s = solver.DefaultSolver(test_config, iface_cache, Stores())
96 foo = iface_cache.get_interface('http://foo/MultiArch.xml')
97 reader.update(foo, 'MultiArch.xml')
98 lib = iface_cache.get_interface('http://foo/MultiArchLib.xml')
99 reader.update(lib, 'MultiArchLib.xml')
101 # On an i686 system we can only use the i486 implementation
103 binary_arch = arch.get_architecture('Linux', 'i686')
104 s.solve('http://foo/MultiArch.xml', binary_arch)
105 assert s.ready
106 assert s.selections[foo].machine == 'i486'
107 assert s.selections[lib].machine == 'i486'
109 # On an 64 bit system we could use either, but we prefer the 64
110 # bit implementation. The i486 version of the library is newer,
111 # but we must pick one that is compatible with the main binary.
113 binary_arch = arch.get_architecture('Linux', 'x86_64')
114 s.solve('http://foo/MultiArch.xml', binary_arch)
115 assert s.ready
116 assert s.selections[foo].machine == 'x86_64'
117 assert s.selections[lib].machine == 'x86_64'
119 def testArch(self):
120 host_arch = arch.get_host_architecture()
121 host_arch2 = arch.get_architecture(None, None)
122 self.assertEquals(host_arch.os_ranks, host_arch2.os_ranks)
123 self.assertEquals(host_arch.machine_ranks, host_arch2.machine_ranks)
125 other = arch.get_architecture('FooBar', 'i486')
126 self.assertEquals(2, len(other.os_ranks))
128 assert 'FooBar' in other.os_ranks
129 assert None in other.os_ranks
130 assert 'i486' in other.machine_ranks
131 assert 'ppc' not in other.machine_ranks
133 def testRanking(self):
134 s = solver.DefaultSolver(test_config, iface_cache, Stores())
135 ranking = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'Ranking.xml')
136 iface = iface_cache.get_interface(ranking)
138 binary_arch = arch.get_architecture('Linux', 'x86_64')
139 selected = []
140 while True:
141 s.solve(ranking, binary_arch)
142 if not s.ready:
143 break
144 impl = s.selections[iface]
145 selected.append(impl.get_version() + ' ' + impl.arch)
146 impl.arch = 'Foo-odd' # prevent reselection
147 self.assertEquals([
148 '0.2 Linux-i386', # poor arch, but newest version
149 '0.1 Linux-x86_64', # 64-bit is best match for host arch
150 '0.1 Linux-i686', '0.1 Linux-i586', '0.1 Linux-i486'], # ordering of x86 versions
151 selected)
153 def testLangs(self):
154 try:
155 locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
157 s = solver.DefaultSolver(test_config, iface_cache, Stores())
158 iface = iface_cache.get_interface('http://foo/Langs.xml')
159 reader.update(iface, 'Langs.xml')
161 # 1 is the oldest, but the only one in our language
162 binary_arch = arch.get_architecture(None, 'arch_1')
163 s.solve('http://foo/Langs.xml', binary_arch)
164 assert s.ready
165 self.assertEquals('sha1=1', s.selections[iface].id)
167 # 6 is the newest, and close enough, even though not
168 # quite the right locale
169 binary_arch = arch.get_architecture(None, 'arch_2')
170 s.solve('http://foo/Langs.xml', binary_arch)
171 assert s.ready
172 self.assertEquals('sha1=6', s.selections[iface].id)
174 # 9 is the newest, although 7 is a closer match
175 binary_arch = arch.get_architecture(None, 'arch_3')
176 s.solve('http://foo/Langs.xml', binary_arch)
177 assert s.ready
178 self.assertEquals('sha1=9', s.selections[iface].id)
180 # 11 is the newest we understand
181 binary_arch = arch.get_architecture(None, 'arch_4')
182 s.solve('http://foo/Langs.xml', binary_arch)
183 assert s.ready
184 self.assertEquals('sha1=11', s.selections[iface].id)
186 # 13 is the newest we understand
187 binary_arch = arch.get_architecture(None, 'arch_5')
188 s.solve('http://foo/Langs.xml', binary_arch)
189 assert s.ready
190 self.assertEquals('sha1=13', s.selections[iface].id)
192 def check(target_arch, langs, expected):
193 s.langs = langs
194 binary_arch = arch.get_architecture(None, target_arch)
195 s.solve('http://foo/Langs.xml', binary_arch)
196 assert s.ready
197 self.assertEquals(expected, s.selections[iface].id)
199 # We don't understand any, so pick the newest
200 check('arch_2', ['es_ES'], 'sha1=6')
202 # These two have the same version number. Choose the
203 # one most appropriate to our country
204 check('arch_6', ['zh_CN'], 'sha1=15')
205 check('arch_6', ['zh_TW'], 'sha1=16')
207 # Same, but one doesn't have a country code
208 check('arch_7', ['bn'], 'sha1=17')
209 check('arch_7', ['bn_IN'], 'sha1=18')
210 finally:
211 locale.setlocale(locale.LC_ALL, '')
213 if __name__ == '__main__':
214 unittest.main()