When autocompiling, get the top-level interface from the feed
[0compile.git] / tests / testcompile.py
blob52da96882cc0d1ce47ffaa11f5510080fd955b67
1 #!/usr/bin/env python
2 import sys, tempfile, os, shutil, tempfile, subprocess
3 from StringIO import StringIO
4 import unittest
5 from zeroinstall.injector import model, qdom, config
6 from zeroinstall.support import ro_rmtree, basedir
7 from zeroinstall.zerostore import Stores
9 stores = Stores()
11 my_dir = os.path.abspath(os.path.dirname(__file__))
12 sys.path.insert(0, os.path.dirname(my_dir))
13 import support
15 hello_uri = 'http://0install.net/tests/GNU-Hello.xml'
16 hello_selections = os.path.realpath(os.path.join(os.path.dirname(__file__), 'selections.xml'))
17 local_bad_version = os.path.realpath(os.path.join(os.path.dirname(__file__), 'bad-version.xml'))
18 local_hello_path = os.path.realpath(os.path.join(os.path.dirname(__file__), 'hello2', 'hello2.xml'))
19 local_cprog_command_path = os.path.realpath(os.path.join(os.path.dirname(__file__), 'cprog', 'cprog-command.xml'))
20 local_cprog_path = os.path.realpath(os.path.join(os.path.dirname(__file__), 'cprog', 'cprog.xml'))
22 compile_bin = os.path.join(my_dir, '0compile-coverage')
23 assert os.path.exists(compile_bin)
25 if 'DISPLAY' in os.environ:
26 del os.environ['DISPLAY']
28 zeroinstall_dir = os.environ.get('0COMPILE_ZEROINSTALL', None)
29 if zeroinstall_dir:
30 launch_command = [sys.executable, os.path.join(zeroinstall_dir, '0launch')]
31 if not os.path.exists(launch_command[1]):
32 launch_command[1] = os.path.join(zeroinstall_dir, 'zeroinstall', 'scripts', 'launch.py')
33 else:
34 launch_command = ['0launch'] # Package
36 # Ensure it's cached now, to avoid extra output during the tests
37 if subprocess.call(launch_command + ['--source', '-vc', '--download-only', hello_uri]):
38 raise Exception("Failed to download hello world test program")
40 def compile(*args, **kwargs):
41 run(*([sys.executable, compile_bin] + list(args)), **kwargs)
43 def run(*args, **kwargs):
44 if not isinstance(args[0], basestring):
45 args = args[0] + list(args[1:])
46 child = subprocess.Popen(args, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
47 got, unused = child.communicate()
48 code = child.wait()
49 if code != kwargs.get('expect_status', 0):
50 raise Exception("Exit status %d:\n%s" % (code, got))
52 expected = kwargs.get('expect', '')
53 if expected:
54 if expected.lower() not in got.lower():
55 raise Exception("Expected '%s', got '%s'" % (expected, got))
56 elif got:
57 raise Exception("Expected nothing, got '%s'" % got)
59 # Detect accidental network access
60 os.environ['http_proxy'] = 'localhost:1111'
62 for x in ['GNUPGHOME', 'XDG_CONFIG_HOME', 'XDG_CACHE_HOME']:
63 if x in os.environ:
64 del os.environ[x]
65 user_cache_dir = os.environ['XDG_CACHE_DIRS'] = basedir.xdg_cache_home
67 class TestCompile(unittest.TestCase):
68 def setUp(self):
69 os.chdir('/')
70 self.tmpdir = tempfile.mkdtemp(prefix = '0compile-test-')
71 self.hello_dir = os.path.join(self.tmpdir, 'hello')
73 os.environ['HOME'] = self.tmpdir
74 reload(basedir)
76 config_dir = basedir.save_config_path('0install.net', 'injector')
77 stream = open(os.path.join(config_dir, 'implementation-dirs'), 'w')
78 for x in stores.stores:
79 stream.write(x.dir + '\n')
80 stream.close()
82 stream = open(os.path.join(config_dir, 'global'), 'w')
83 stream.write('[global]\n'
84 'freshness = -1\n'
85 'help_with_testing = True\n'
86 'network_use = off-line\n')
87 stream.close()
89 def tearDown(self):
90 ro_rmtree(self.tmpdir)
92 def testBadCommand(self):
93 compile('foo', expect = 'usage: 0compile', expect_status = 1)
94 compile('setup', hello_uri, self.tmpdir, expect = 'already exists', expect_status = 1)
95 os.chdir(self.tmpdir)
96 compile('setup', expect = 'Run 0compile from a directory containing', expect_status = 1)
97 compile('build', expect = 'Run 0compile from a directory containing', expect_status = 1)
98 compile('publish', expect = 'Run 0compile from a directory containing', expect_status = 1)
100 def testCompileNoDir(self):
101 os.chdir(self.tmpdir)
102 compile('setup', hello_uri, expect = 'Created directory')
103 os.chdir('GNU-Hello')
105 def testCompile(self):
106 compile('setup', hello_uri, self.hello_dir, expect = 'Created directory')
107 os.chdir(self.hello_dir)
109 compile('build', expect = 'Executing: "%s"' % os.path.join('$SRCDIR','configure'))
111 target_dir = 'gnu-hello-%s' % support.get_arch_name().lower()
112 archive_stem = 'gnu-hello-%s-1.3' % support.get_arch_name().lower()
113 assert os.path.isdir(target_dir), '%s not a directory' % target_dir
115 run(os.path.join(target_dir,'bin','hello'), expect = 'Hello, world!')
116 run(launch_command, os.path.join(target_dir,'0install','GNU-Hello.xml'), expect = 'Hello, world!')
117 compile('publish', 'http://localhost/downloads', expect = "Now upload '%s.tar.bz2'" % archive_stem)
119 def testAutocompile(self):
120 compile('autocompile', hello_uri, expect = "Registering as feed for http://0install.net/tests/GNU-Hello.xml")
121 run(launch_command, hello_uri, expect = 'Hello, world!')
123 def testRecursive(self):
124 top = os.path.join(my_dir, 'top.xml')
125 compile('autocompile', top, expect = "No dependencies need compiling... compile cprog itself...")
127 # Dependency was registered against its local path, since that was how we depended on it:
128 run(launch_command, os.path.join(my_dir, 'cprog/cprog-command.xml'), expect = 'Hello from C')
130 # But the top-level feed was registered against its <feed-for>:
131 c = config.load_config()
132 i = c.iface_cache.get_interface('http://example.com/top.xml')
133 self.assertEquals(1, len(i.extra_feeds))
135 def testLocal(self):
136 compile('setup', local_hello_path, self.hello_dir, expect = 'Created directory')
137 os.chdir(self.hello_dir)
138 compile('build', expect = 'Executing: ls -l')
139 target_dir = 'hello2-any-any'
140 assert os.path.isdir(target_dir), '%s not a directory' % target_dir
142 run(launch_command, os.path.join(target_dir, '0install', 'hello2.xml'), expect = 'ROX-Lib')
144 def testBadVersion(self):
145 compile('setup', local_bad_version, self.hello_dir, expect = 'Created directory')
146 os.chdir(self.hello_dir)
147 compile('build', expect = 'hello2-0.1 requires 0compile >= 300000', expect_status = 1)
149 def testCommand(self):
150 comp_dir = os.path.join(self.tmpdir, 'cprog-command')
151 compile('setup', local_cprog_command_path, comp_dir, expect = 'Created directory')
152 os.chdir(comp_dir)
153 compile('build', expect = 'Hello from C!')
154 target_dir = 'cprog-command-%s' % support.get_arch_name().lower()
155 binary_feed = os.path.join(target_dir, '0install', 'cprog-command.xml')
156 run(launch_command, binary_feed, expect = 'Hello from C!')
157 s = open(binary_feed, 'r')
158 feed = model.ZeroInstallFeed(qdom.parse(s), binary_feed)
159 s.close()
160 impl, = feed.implementations.values()
161 assert impl.arch, "Missing arch on %s" % impl
163 def testCopySrc(self):
164 comp_dir = os.path.join(self.tmpdir, 'cprog')
165 compile('setup', local_cprog_path, comp_dir, expect = 'Created directory')
166 os.chdir(comp_dir)
167 compile('diff', expect = "No local src directory to diff against", expect_status = 1)
168 compile('diff', 'foo', expect = 'usage', expect_status = 1)
169 compile('copy-src', 'foo', expect = 'usage', expect_status = 1)
170 compile('copy-src', expect = 'Copied as')
171 compile('copy-src', expect = "Directory '", expect_status = 1)
173 # 'src' exists, but no changes
174 compile('diff')
175 compile('--verbose', 'build', expect = 'Hello from C')
176 target_dir = 'cprog-%s' % support.get_arch_name().lower()
177 patch_file = os.path.join(target_dir, '0install', 'from-0.1.patch')
178 assert not os.path.exists(patch_file)
180 # 'src' contains a change
181 prog = file(os.path.join('src','main.c')).read()
182 prog = prog.replace('Hello', 'Goodbye')
183 stream = file(os.path.join('src','main.c'), 'w')
184 stream.write(prog)
185 stream.close()
186 compile('diff', expect = 'diff')
187 shutil.rmtree('build')
188 compile('build', expect = 'Goodbye from C')
189 assert os.path.exists(patch_file)
191 # Test dup-src's unlinking while we're here
192 compile('build', expect = 'Goodbye from C')
194 # 'src' contains an error
195 stream = file(os.path.join('src','main.c'), 'w')
196 stream.write('this is not valid C!')
197 stream.close()
198 shutil.rmtree('build')
199 compile('build', expect = 'Build failed', expect_status = 1)
200 assert os.path.exists(os.path.join('build', 'build-failure.log'))
202 # 'src' does not exist
203 shutil.rmtree('src')
204 shutil.rmtree('build')
205 compile('build', expect = 'Hello from C')
206 assert not os.path.exists(patch_file)
208 # Check we fixed the .pc files...
209 pc_data = open(os.path.join(target_dir, 'pkgconfig', 'cprog.pc')).read()
210 assert pc_data == "prefix=" + os.path.join("${pcfiledir}",os.path.pardir) + "\n", `pc_data`
212 # Check we removed the bad .la files...
213 assert not os.path.exists(os.path.join(target_dir, 'lib', 'bad.la')) # libtool - bad
214 assert os.path.exists(os.path.join(target_dir, 'lib', 'good.la')) # Ends in .la, but not a libtool archive
215 assert os.path.exists(os.path.join(target_dir, 'lib', 'nice.ok')) # Doesn't end in .la
217 def testInlcudeDeps(self):
218 compile('setup', hello_uri, self.hello_dir, expect = 'Created directory')
219 os.chdir(self.hello_dir)
220 os.unlink('0compile.properties')
221 compile('setup', hello_uri, '.')
222 compile('include-deps', expect = 'dependencies to')
223 compile('include-deps', expect = 'Copied 0 depend')
225 def testSetup(self):
226 compile('setup', hello_selections, self.hello_dir,
227 expect = 'Created directory')
228 compile('setup', hello_selections, self.hello_dir,
229 expect = "Directory '", expect_status = 1)
230 compile('setup', hello_selections, '.', 'foo',
231 expect = "usage", expect_status = 1)
232 os.chdir(self.hello_dir)
233 compile('setup', expect = "Selections are fixed", expect_status = 1)
235 def testReportBug(self):
236 broken_src = os.path.join(self.hello_dir, "broken.xml")
237 os.mkdir(self.hello_dir)
238 shutil.copy(local_hello_path, broken_src)
239 os.chdir(self.hello_dir)
240 compile('setup', broken_src, '.')
241 compile('build', expect = 'Build failed with exit code', expect_status = 1)
242 compile('report-bug', expect = "http://sourceforge.net")
244 env = support.BuildEnv()
245 os.unlink(os.path.join(env.metadir, "build-environment.xml"))
246 compile('report-bug', expect = "file+not+found")
248 suite = unittest.makeSuite(TestCompile)
249 if __name__ == '__main__':
250 unittest.main()