Updated unit-tests for latest 0repo
[0release.git] / tests / testrelease.py
blob30719fad36e30020466e00cb62abc2be9aebc55a
1 #!/usr/bin/env python
2 # Copyright (C) 2007, Thomas Leonard
3 # See the README file for details, or visit http://0install.net.
4 import sys, os, shutil, tempfile, subprocess, imp
5 from StringIO import StringIO
6 import unittest
8 from zeroinstall.injector import model, qdom, writer
9 from zeroinstall.injector.config import load_config
10 from zeroinstall.support import basedir, ro_rmtree
12 sys.path.insert(0, '..')
13 os.environ['http_proxy'] = 'localhost:1111' # Prevent accidental network access
15 import support
16 import release # (sets sys.path for 0repo)
17 import repo.cmd
19 mydir = os.path.realpath(os.path.dirname(__file__))
20 release_feed = mydir + '/../0release.xml'
21 test_repo = mydir + '/test-repo.tgz'
22 test_repo_actions = mydir + '/test-repo-actions.tgz'
23 test_repo_c = mydir + '/c-prog.tgz'
24 test_gpg = mydir + '/gpg.tgz'
26 test_config = """
27 [global]
28 freshness = 0
29 auto_approve_keys = True
30 help_with_testing = True
31 network_use = full
32 """
34 CUSTOM_REPO_CONFIG = """
35 REPOSITORY_BASE_URL = "http://0install.net/tests/"
36 ARCHIVES_BASE_URL = "http://TESTING/releases"
38 def upload_archives(archives):
39 for dir_rel_url, files in paths.group_by_target_url_dir(archives):
40 target_dir = join('..', 'releases', 'archives') # hack: skip dir_rel_url
41 if not os.path.isdir(target_dir):
42 os.makedirs(target_dir)
43 subprocess.check_call(["cp"] + files + [target_dir])
45 def check_new_impl(impl):
46 pass
48 def get_archive_rel_url(archive_basename, impl):
49 return "{version}/{archive}".format(
50 version = impl.get_version(),
51 archive = archive_basename)
53 def check_uploaded_archive(archive, url):
54 pass
55 """
57 def call_with_output_suppressed(cmd, stdin, expect_failure = False, **kwargs):
58 #cmd = [cmd[0], '-v'] + cmd[1:]
59 if stdin:
60 child = subprocess.Popen(cmd, stdin = subprocess.PIPE, stdout = subprocess.PIPE, **kwargs)
61 else:
62 child = subprocess.Popen(cmd, stdout = subprocess.PIPE, **kwargs)
63 stdout, stderr = child.communicate(stdin)
64 if (child.returncode != 0) == expect_failure:
65 return stdout, stderr
66 #print stdout, stderr
67 raise Exception("Return code %d from %s\nstdout: %s\nstderr: %s" % (child.returncode, cmd, stdout, stderr))
69 def make_releases_dir(src_feed = '../hello/HelloWorld.xml', auto_upload = False):
70 os.chdir('releases')
71 call_with_output_suppressed(['0release', src_feed], None)
72 assert os.path.isfile('make-release')
74 lines = file('make-release').readlines()
75 lines[lines.index('ARCHIVE_DIR_PUBLIC_URL=\n')] = 'ARCHIVE_DIR_PUBLIC_URL=http://TESTING/releases/\\$RELEASE_VERSION\n'
77 # Force us to test against this version of 0release
78 for i, line in enumerate(lines):
79 if line.startswith('exec 0launch http://0install.net/2007/interfaces/0release.xml --release'):
80 lines[i] = '0release --release ' + line.split('--release ', 1)[1]
81 break
82 else:
83 assert 0
85 if auto_upload:
86 os.mkdir('archives')
87 lines[lines.index('ARCHIVE_UPLOAD_COMMAND=\n')] = 'ARCHIVE_UPLOAD_COMMAND=\'cp "$@" ../archives/\'\n'
89 s = file('make-release', 'w')
90 s.write(''.join(lines))
91 s.close()
93 class TestRelease(unittest.TestCase):
94 def setUp(self):
95 self.tmp = tempfile.mkdtemp(prefix = '0release-')
96 os.chdir(self.tmp)
97 support.check_call(['tar', 'xzf', test_gpg])
98 os.mkdir('releases')
99 os.environ['GNUPGHOME'] = self.tmp + '/gpg'
100 os.chmod(os.environ['GNUPGHOME'], 0700)
102 config_dir = os.path.join(self.tmp, 'config')
103 injector_config = os.path.join(config_dir, '0install.net', 'injector')
104 os.makedirs(injector_config)
105 s = open(os.path.join(injector_config, 'global'), 'w')
106 s.write(test_config)
107 s.close()
109 if 'ZEROINSTALL_PORTABLE_BASE' in os.environ:
110 del os.environ['ZEROINSTALL_PORTABLE_BASE']
111 os.environ['XDG_CONFIG_HOME'] = config_dir
112 imp.reload(basedir)
113 assert basedir.xdg_config_home == config_dir
115 def tearDown(self):
116 os.chdir(mydir)
117 ro_rmtree(self.tmp)
119 def testSimple(self):
120 support.check_call(['tar', 'xzf', test_repo])
121 make_releases_dir()
123 call_with_output_suppressed(['./make-release', '-k', 'Testing'], '\nP\n\n')
125 call_with_output_suppressed(['./make-release', '-k', 'Testing'], '\nP\nY\n\n')
127 assert 'Prints "Hello World"' in file('0.1/changelog-0.1').read()
128 assert 'Prints "Hello World"' not in file('0.2/changelog-0.2').read()
130 def testUncommitted(self):
131 support.check_call(['tar', 'xzf', test_repo_actions])
132 make_releases_dir()
134 unused, stderr = call_with_output_suppressed(['./make-release', '-k', 'Testing'], None,
135 expect_failure = True, stderr = subprocess.PIPE)
136 assert "Uncommitted changes!" in stderr
138 def testActions(self):
139 support.check_call(['tar', 'xzf', test_repo_actions])
140 os.chdir('hello')
141 support.check_call(['git', 'commit', '-a', '-m', 'Added release instructions'], stdout = subprocess.PIPE)
142 os.chdir('..')
143 make_releases_dir()
145 assert "version = '0.2'\n" not in file('../hello/hello.py').read()
147 child = subprocess.Popen(['./make-release', '-k', 'Testing'], stdin = subprocess.PIPE, stdout = subprocess.PIPE)
148 unused, unused = child.communicate('\nP\n\n')
149 assert child.returncode == 0
151 assert "version = '0.2'\n" in file('../hello/hello.py').read()
153 def testBinaryRelease(self):
154 support.check_call(['tar', 'xzf', test_repo_c])
155 make_releases_dir(src_feed = '../c-prog/c-prog.xml', auto_upload = True)
157 call_with_output_suppressed(['./make-release', '-k', 'Testing', '--builders=host'], '\nP\n\n')
159 feed = self.get_public_feed('HelloWorld-in-C.xml', 'c-prog.xml')
161 assert len(feed.implementations) == 2
162 src_impl, = [x for x in feed.implementations.values() if x.arch == '*-src']
163 host_impl, = [x for x in feed.implementations.values() if x.arch != '*-src']
165 assert src_impl.main == None
166 assert host_impl.main == 'hello'
168 archives = os.listdir('archives')
169 assert os.path.basename(src_impl.download_sources[0].url) in archives, src_impl.download_sources[0].url
171 host_download = host_impl.download_sources[0]
172 self.assertEqual('http://TESTING/releases/1.1/helloworld-in-c-linux-x86_64-1.1.tar.bz2',
173 host_download.url)
174 host_archive = os.path.basename(host_download.url)
175 assert host_archive in archives
176 support.check_call(['tar', 'xjf', os.path.join('archives', host_archive)])
177 c = subprocess.Popen(['0launch', os.path.join(host_download.extract, '0install', 'feed.xml')], stdout = subprocess.PIPE)
178 output, _ = c.communicate()
180 self.assertEquals("Hello from C! (version 1.1)\n", output)
182 def get_public_feed(self, name, uri_basename):
183 with open(name, 'rb') as stream:
184 return model.ZeroInstallFeed(qdom.parse(stream))
186 def run_repo(args):
187 oldcwd = os.getcwd()
189 old_stdout = sys.stdout
190 sys.stdout = StringIO()
191 try:
192 sys.stdin = StringIO('\n') # (simulate a press of Return if needed)
193 repo.cmd.main(['0repo'] + args)
194 return sys.stdout.getvalue()
195 finally:
196 os.chdir(oldcwd)
197 sys.stdout = old_stdout
199 class TestRepoRelease(TestRelease):
200 def setUp(self):
201 TestRelease.setUp(self)
203 # Let GPG initialise (it's a bit verbose)
204 child = subprocess.Popen(['gpg', '-q', '--list-secret-keys'], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
205 unused, unused = child.communicate()
206 child.wait()
208 run_repo(['create', 'my-repo', 'Testing <testing@example.com>'])
209 os.chdir('my-repo')
211 if '0repo-config' in sys.modules:
212 del sys.modules['0repo-config']
214 with open('0repo-config.py', 'at') as stream:
215 stream.write(CUSTOM_REPO_CONFIG)
216 run_repo(['register'])
217 os.chdir('..')
219 def get_public_feed(self, name, uri_basename):
220 with open(os.path.join(self.tmp, 'my-repo', 'public', uri_basename), 'rb') as stream:
221 return model.ZeroInstallFeed(qdom.parse(stream))
223 unittest.makeSuite(TestRelease)
224 unittest.makeSuite(TestRepoRelease)
225 if __name__ == '__main__':
226 unittest.main()