Added Fetch.download_url
[zeroinstall.git] / tests / testsolver.py
blobfec0a81bc9ff9c64ed388b73c8e296a5fcf79e9f
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 mydir = os.path.dirname(os.path.abspath(__file__))
14 command_dep = os.path.join(mydir, 'command-dep.xml')
16 class TestSolver(BaseTest):
17 def testSimple(self):
18 iface_cache = self.config.iface_cache
19 s = solver.DefaultSolver(self.config)
21 foo = iface_cache.get_interface('http://foo/Binary.xml')
22 self.import_feed(foo.uri, 'Binary.xml')
23 foo_src = iface_cache.get_interface('http://foo/Source.xml')
24 self.import_feed(foo_src.uri, 'Source.xml')
25 compiler = iface_cache.get_interface('http://foo/Compiler.xml')
26 self.import_feed(compiler.uri, 'Compiler.xml')
28 binary_arch = arch.Architecture({None: 1}, {None: 1})
29 assert str(binary_arch).startswith("<Arch")
30 s.solve('http://foo/Binary.xml', binary_arch)
32 assert s.ready
33 assert s.feeds_used == set([foo.uri]), s.feeds_used
34 assert s.selections[foo].id == 'sha1=123'
36 # Now ask for source instead
37 s.solve('http://foo/Binary.xml',
38 arch.SourceArchitecture(binary_arch),
39 command_name = 'compile')
40 assert s.ready, s.get_failure_reason()
41 assert s.feeds_used == set([foo.uri, foo_src.uri, compiler.uri]), s.feeds_used
42 assert s.selections[foo].id == 'sha1=234' # The source
43 assert s.selections[compiler].id == 'sha1=345' # A binary needed to compile it
45 assert not s.details
47 def testCommand(self):
48 s = solver.DefaultSolver(self.config)
49 binary_arch = arch.Architecture({None: 1}, {None: 1})
50 s.solve(command_dep, binary_arch)
51 command = s.selections.selections[s.selections.interface].get_command("run")
52 dep, = command.requires
53 dep_impl = s.selections.selections[dep.interface]
54 assert dep_impl.get_command("run").path == "test-gui"
56 def testDetails(self):
57 iface_cache = self.config.iface_cache
58 s = solver.DefaultSolver(self.config)
60 foo_binary_uri = 'http://foo/Binary.xml'
61 foo = iface_cache.get_interface(foo_binary_uri)
62 self.import_feed(foo_binary_uri, 'Binary.xml')
63 foo_src = iface_cache.get_interface('http://foo/Source.xml')
64 self.import_feed(foo_src.uri, 'Source.xml')
65 compiler = iface_cache.get_interface('http://foo/Compiler.xml')
66 self.import_feed(compiler.uri, 'Compiler.xml')
68 binary_arch = arch.Architecture({None: 1}, {None: 1})
69 s.record_details = True
70 s.solve('http://foo/Binary.xml', arch.SourceArchitecture(binary_arch), command_name = 'compile')
71 assert s.ready, s.get_failure_reason()
73 foo_src_impls = iface_cache.get_feed(foo_src.uri).implementations
74 foo_impls = iface_cache.get_feed(foo.uri).implementations
75 compiler_impls = iface_cache.get_feed(compiler.uri).implementations
77 assert len(s.details) == 2
78 self.assertEqual([(foo_src_impls['sha1=234'], None),
79 (foo_impls['sha1=123'], 'Unsupported machine type')],
80 sorted(s.details[foo]))
81 assert s.details[compiler] == [(compiler_impls['sha1=345'], None)]
83 def testRecursive(self):
84 iface_cache = self.config.iface_cache
85 s = solver.DefaultSolver(self.config)
87 foo = iface_cache.get_interface('http://foo/Recursive.xml')
88 self.import_feed(foo.uri, 'Recursive.xml')
90 binary_arch = arch.Architecture({None: 1}, {None: 1})
91 s.record_details = True
92 s.solve('http://foo/Recursive.xml', binary_arch)
93 assert s.ready
95 foo_impls = iface_cache.get_feed(foo.uri).implementations
97 assert len(s.details) == 1
98 assert s.details[foo] == [(foo_impls['sha1=abc'], None)]
100 def testMultiArch(self):
101 iface_cache = self.config.iface_cache
102 s = solver.DefaultSolver(self.config)
104 foo = iface_cache.get_interface('http://foo/MultiArch.xml')
105 self.import_feed(foo.uri, 'MultiArch.xml')
106 lib = iface_cache.get_interface('http://foo/MultiArchLib.xml')
107 self.import_feed(lib.uri, 'MultiArchLib.xml')
109 # On an i686 system we can only use the i486 implementation
111 binary_arch = arch.get_architecture('Linux', 'i686')
112 s.solve('http://foo/MultiArch.xml', binary_arch)
113 assert s.ready
114 assert s.selections[foo].machine == 'i486'
115 assert s.selections[lib].machine == 'i486'
117 # On an 64 bit system we could use either, but we prefer the 64
118 # bit implementation. The i486 version of the library is newer,
119 # but we must pick one that is compatible with the main binary.
121 binary_arch = arch.get_architecture('Linux', 'x86_64')
122 s.solve('http://foo/MultiArch.xml', binary_arch)
123 assert s.ready
124 assert s.selections[foo].machine == 'x86_64'
125 assert s.selections[lib].machine == 'x86_64'
127 def testArch(self):
128 host_arch = arch.get_host_architecture()
129 host_arch2 = arch.get_architecture(None, None)
130 self.assertEqual(host_arch.os_ranks, host_arch2.os_ranks)
131 self.assertEqual(host_arch.machine_ranks, host_arch2.machine_ranks)
133 other = arch.get_architecture('FooBar', 'i486')
134 self.assertEqual(2, len(other.os_ranks))
136 assert 'FooBar' in other.os_ranks
137 assert None in other.os_ranks
138 assert 'i486' in other.machine_ranks
139 assert 'ppc' not in other.machine_ranks
141 def testRanking(self):
142 iface_cache = self.config.iface_cache
143 s = solver.DefaultSolver(self.config)
144 ranking = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'Ranking.xml')
145 iface = iface_cache.get_interface(ranking)
147 binary_arch = arch.get_architecture('Linux', 'x86_64')
148 selected = []
149 while True:
150 s.solve(ranking, binary_arch)
151 if not s.ready:
152 break
153 impl = s.selections[iface]
154 selected.append(impl.get_version() + ' ' + impl.arch)
155 impl.arch = 'Foo-odd' # prevent reselection
156 self.assertEqual([
157 '0.2 Linux-i386', # poor arch, but newest version
158 '0.1 Linux-x86_64', # 64-bit is best match for host arch
159 '0.1 Linux-i686', '0.1 Linux-i586', '0.1 Linux-i486'], # ordering of x86 versions
160 selected)
162 def testLangs(self):
163 iface_cache = self.config.iface_cache
164 try:
165 locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
167 s = solver.DefaultSolver(self.config)
168 iface = iface_cache.get_interface('http://foo/Langs.xml')
169 self.import_feed(iface.uri, 'Langs.xml')
171 # 1 is the oldest, but the only one in our language
172 binary_arch = arch.get_architecture(None, 'arch_1')
173 s.solve('http://foo/Langs.xml', binary_arch)
174 assert s.ready
175 self.assertEqual('sha1=1', s.selections[iface].id)
177 # 6 is the newest, and close enough, even though not
178 # quite the right locale
179 binary_arch = arch.get_architecture(None, 'arch_2')
180 s.solve('http://foo/Langs.xml', binary_arch)
181 assert s.ready
182 self.assertEqual('sha1=6', s.selections[iface].id)
184 # 9 is the newest, although 7 is a closer match
185 binary_arch = arch.get_architecture(None, 'arch_3')
186 s.solve('http://foo/Langs.xml', binary_arch)
187 assert s.ready
188 self.assertEqual('sha1=9', s.selections[iface].id)
190 # 11 is the newest we understand
191 binary_arch = arch.get_architecture(None, 'arch_4')
192 s.solve('http://foo/Langs.xml', binary_arch)
193 assert s.ready
194 self.assertEqual('sha1=11', s.selections[iface].id)
196 # 13 is the newest we understand
197 binary_arch = arch.get_architecture(None, 'arch_5')
198 s.solve('http://foo/Langs.xml', binary_arch)
199 assert s.ready
200 self.assertEqual('sha1=13', s.selections[iface].id)
202 def check(target_arch, langs, expected):
203 s.langs = langs
204 binary_arch = arch.get_architecture(None, target_arch)
205 s.solve('http://foo/Langs.xml', binary_arch)
206 assert s.ready
207 self.assertEqual(expected, s.selections[iface].id)
209 # We don't understand any, so pick the newest
210 check('arch_2', ['es_ES'], 'sha1=6')
212 # These two have the same version number. Choose the
213 # one most appropriate to our country
214 check('arch_6', ['zh_CN'], 'sha1=15')
215 check('arch_6', ['zh_TW'], 'sha1=16')
217 # Same, but one doesn't have a country code
218 check('arch_7', ['bn'], 'sha1=17')
219 check('arch_7', ['bn_IN'], 'sha1=18')
220 finally:
221 locale.setlocale(locale.LC_ALL, '')
223 def testDecideBug(self):
224 s = solver.DefaultSolver(self.config)
225 watch_xml = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'watchdog.xml')
226 s.solve(watch_xml, arch.get_architecture(None, None), command_name = 'test')
228 if __name__ == '__main__':
229 unittest.main()