Improved error reporting when no main executable is given
[zeroinstall/solver.git] / tests / testrun.py
blob87aa6d2faf5c4d864a91e609a9b8409e6cf2832b
1 #!/usr/bin/env python
2 from basetest import BaseTest, StringIO
3 import os, sys, subprocess
4 import unittest
6 sys.path.insert(0, '..')
8 # (testing command support imports zeroinstall.injector._runenv in a sub-process)
9 os.environ['PYTHONPATH'] = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
11 from zeroinstall.support import tasks
12 from zeroinstall.injector import run, namespaces
13 from zeroinstall import SafeException
14 from zeroinstall.injector.requirements import Requirements
15 from zeroinstall.injector.driver import Driver
16 from zeroinstall.support import unicode
18 mydir = os.path.abspath(os.path.dirname(__file__))
19 local_0launch = os.path.join(os.path.dirname(mydir), '0launch')
20 runnable = os.path.join(mydir, 'runnable', 'Runnable.xml')
21 runexec = os.path.join(mydir, 'runnable', 'RunExec.xml')
22 recursive_runner = os.path.join(mydir, 'runnable', 'RecursiveRunner.xml')
23 command_feed = os.path.join(mydir, 'Command.xml')
24 package_selections = os.path.join(mydir, 'package-selection.xml')
26 class TestRun(BaseTest):
27 def testRunnable(self):
28 child = subprocess.Popen([local_0launch, '--', runnable, 'user-arg'], stdout = subprocess.PIPE, universal_newlines = True)
29 stdout, _ = child.communicate()
30 assert 'Runner: script=A test script: args=command-arg -- user-arg' in stdout, stdout
32 def testCommandBindings(self):
33 if 'SELF_COMMAND' in os.environ:
34 del os.environ['SELF_COMMAND']
36 p = Driver(requirements = Requirements(command_feed), config = self.config)
37 tasks.wait_for_blocker(p.solve_with_downloads())
38 old_stdout = sys.stdout
39 try:
40 sys.stdout = StringIO()
41 run.execute_selections(p.solver.selections, [], main = 'runnable/go.sh', dry_run = True, stores = self.config.stores)
42 finally:
43 sys.stdout = old_stdout
44 assert 'local' in os.environ['LOCAL'], os.environ['LOCAL']
45 assert 'SELF_COMMAND' in os.environ
47 def testAbsMain(self):
48 p = Driver(requirements = Requirements(command_feed), config = self.config)
49 self.config.handler.wait_for_blocker(p.solve_with_downloads())
51 old_stdout = sys.stdout
52 try:
53 sys.stdout = StringIO()
54 run.execute_selections(p.solver.selections, [], main = '/runnable/runner', dry_run = True, stores = self.config.stores)
55 finally:
56 sys.stdout = old_stdout
58 try:
59 old_stdout = sys.stdout
60 try:
61 sys.stdout = StringIO()
62 run.execute_selections(p.solver.selections, [], main = '/runnable/not-there', dry_run = True, stores = self.config.stores)
63 finally:
64 sys.stdout = old_stdout
65 except SafeException as ex:
66 assert 'not-there' in unicode(ex)
68 def testBadMain(self):
69 r = Requirements(command_feed)
70 r.command = None
71 d = Driver(requirements = r, config = self.config)
72 self.config.handler.wait_for_blocker(d.solve_with_downloads())
74 try:
75 run.execute_selections(d.solver.selections, [], dry_run = True, stores = self.config.stores)
76 assert 0
77 except SafeException as ex:
78 self.assertEqual("Can't run: no command specified!", unicode(ex))
80 try:
81 run.execute_selections(d.solver.selections, [], main = 'relpath', dry_run = True, stores = self.config.stores)
82 assert 0
83 except SafeException as ex:
84 self.assertEqual("Can't use a relative replacement main when there is no original one!", unicode(ex))
86 def testArgs(self):
87 p = Driver(requirements = Requirements(runnable), config = self.config)
88 self.config.handler.wait_for_blocker(p.solve_with_downloads())
89 old_stdout = sys.stdout
90 try:
91 sys.stdout = StringIO()
92 run.execute_selections(p.solver.selections, [], dry_run = True, stores = self.config.stores)
93 out = sys.stdout.getvalue()
94 finally:
95 sys.stdout = old_stdout
96 assert 'runner-arg' in out, out
98 def testWrapper(self):
99 p = Driver(requirements = Requirements(runnable), config = self.config)
100 self.config.handler.wait_for_blocker(p.solve_with_downloads())
101 old_stdout = sys.stdout
102 try:
103 sys.stdout = StringIO()
104 run.execute_selections(p.solver.selections, [], wrapper = 'echo', dry_run = True, stores = self.config.stores)
105 out = sys.stdout.getvalue()
106 finally:
107 sys.stdout = old_stdout
108 assert '/bin/sh -c echo "$@"' in out, out
109 assert 'runner-arg' in out, out
110 assert 'script' in out, out
112 def testRecursive(self):
113 child = subprocess.Popen([local_0launch, '--', recursive_runner, 'user-arg'], stdout = subprocess.PIPE, universal_newlines = True)
114 stdout, _ = child.communicate()
115 assert 'Runner: script=A test script: args=command-arg -- arg-for-runnable recursive-arg -- user-arg' in stdout, stdout
117 def testExecutable(self):
118 child = subprocess.Popen([local_0launch, '--', runexec, 'user-arg-run'], stdout = subprocess.PIPE, universal_newlines = True)
119 stdout, _ = child.communicate()
120 assert 'Runner: script=A test script: args=foo-arg -- var user-arg-run' in stdout, stdout
121 assert 'Runner: script=A test script: args=command-arg -- path user-arg-run' in stdout, stdout
123 # Check runenv.py is updated correctly
124 from zeroinstall.support import basedir
125 runenv = basedir.load_first_cache(namespaces.config_site, namespaces.config_prog, 'runenv.py')
126 os.chmod(runenv, 0o700)
127 with open(runenv, 'wb') as s:
128 s.write(b'#!/\n')
130 child = subprocess.Popen([local_0launch, '--', runexec, 'user-arg-run'], stdout = subprocess.PIPE, universal_newlines = True)
131 stdout, _ = child.communicate()
132 assert 'Runner: script=A test script: args=foo-arg -- var user-arg-run' in stdout, stdout
133 assert 'Runner: script=A test script: args=command-arg -- path user-arg-run' in stdout, stdout
135 def testRunPackage(self):
136 if 'TEST' in os.environ:
137 del os.environ['TEST']
138 child = subprocess.Popen([local_0launch, '--wrapper', 'echo $TEST #', '--', package_selections], stdout = subprocess.PIPE, universal_newlines = True)
139 stdout, _ = child.communicate()
140 assert stdout.strip() == 'OK', stdout
142 if __name__ == '__main__':
143 unittest.main()