|
1 # This Source Code Form is subject to the terms of the Mozilla Public |
|
2 # License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|
4 |
|
5 import os.path |
|
6 import shutil |
|
7 import zipfile |
|
8 from StringIO import StringIO |
|
9 import simplejson as json |
|
10 import unittest |
|
11 import cuddlefish |
|
12 from cuddlefish import packaging, manifest |
|
13 |
|
14 def up(path, generations=1): |
|
15 for i in range(generations): |
|
16 path = os.path.dirname(path) |
|
17 return path |
|
18 |
|
19 ROOT = up(os.path.abspath(__file__), 4) |
|
20 def get_linker_files_dir(name): |
|
21 return os.path.join(up(os.path.abspath(__file__)), "linker-files", name) |
|
22 |
|
23 class Basic(unittest.TestCase): |
|
24 def get_pkg(self, name): |
|
25 d = get_linker_files_dir(name) |
|
26 return packaging.get_config_in_dir(d) |
|
27 |
|
28 def test_deps(self): |
|
29 target_cfg = self.get_pkg("one") |
|
30 pkg_cfg = packaging.build_config(ROOT, target_cfg) |
|
31 deps = packaging.get_deps_for_targets(pkg_cfg, ["one"]) |
|
32 self.failUnlessEqual(deps, ["one"]) |
|
33 deps = packaging.get_deps_for_targets(pkg_cfg, |
|
34 [target_cfg.name, "addon-sdk"]) |
|
35 self.failUnlessEqual(deps, ["addon-sdk", "one"]) |
|
36 |
|
37 def test_manifest(self): |
|
38 target_cfg = self.get_pkg("one") |
|
39 pkg_cfg = packaging.build_config(ROOT, target_cfg) |
|
40 deps = packaging.get_deps_for_targets(pkg_cfg, |
|
41 [target_cfg.name, "addon-sdk"]) |
|
42 self.failUnlessEqual(deps, ["addon-sdk", "one"]) |
|
43 # target_cfg.dependencies is not provided, so we'll search through |
|
44 # all known packages (everything in 'deps'). |
|
45 m = manifest.build_manifest(target_cfg, pkg_cfg, deps, scan_tests=False) |
|
46 m = m.get_harness_options_manifest(False) |
|
47 |
|
48 def assertReqIs(modname, reqname, path): |
|
49 reqs = m["one/%s" % modname]["requirements"] |
|
50 self.failUnlessEqual(reqs[reqname], path) |
|
51 assertReqIs("main", "sdk/panel", "sdk/panel") |
|
52 assertReqIs("main", "two.js", "one/two") |
|
53 assertReqIs("main", "./two", "one/two") |
|
54 assertReqIs("main", "sdk/tabs.js", "sdk/tabs") |
|
55 assertReqIs("main", "./subdir/three", "one/subdir/three") |
|
56 assertReqIs("two", "main", "one/main") |
|
57 assertReqIs("subdir/three", "../main", "one/main") |
|
58 |
|
59 target_cfg.dependencies = [] |
|
60 # now, because .dependencies *is* provided, we won't search 'deps', |
|
61 # so we'll get a link error |
|
62 self.assertRaises(manifest.ModuleNotFoundError, |
|
63 manifest.build_manifest, |
|
64 target_cfg, pkg_cfg, deps, scan_tests=False) |
|
65 |
|
66 def test_main_in_deps(self): |
|
67 target_cfg = self.get_pkg("three") |
|
68 package_path = [get_linker_files_dir("three-deps")] |
|
69 pkg_cfg = packaging.build_config(ROOT, target_cfg, |
|
70 packagepath=package_path) |
|
71 deps = packaging.get_deps_for_targets(pkg_cfg, |
|
72 [target_cfg.name, "addon-sdk"]) |
|
73 self.failUnlessEqual(deps, ["addon-sdk", "three"]) |
|
74 m = manifest.build_manifest(target_cfg, pkg_cfg, deps, scan_tests=False) |
|
75 m = m.get_harness_options_manifest(False) |
|
76 def assertReqIs(modname, reqname, path): |
|
77 reqs = m["three/%s" % modname]["requirements"] |
|
78 self.failUnlessEqual(reqs[reqname], path) |
|
79 assertReqIs("main", "three-a", "three-a/main") |
|
80 assertReqIs("main", "three-b", "three-b/main") |
|
81 assertReqIs("main", "three-c", "three-c/main") |
|
82 |
|
83 def test_relative_main_in_top(self): |
|
84 target_cfg = self.get_pkg("five") |
|
85 package_path = [] |
|
86 pkg_cfg = packaging.build_config(ROOT, target_cfg, |
|
87 packagepath=package_path) |
|
88 deps = packaging.get_deps_for_targets(pkg_cfg, |
|
89 [target_cfg.name, "addon-sdk"]) |
|
90 self.failUnlessEqual(deps, ["addon-sdk", "five"]) |
|
91 # all we care about is that this next call doesn't raise an exception |
|
92 m = manifest.build_manifest(target_cfg, pkg_cfg, deps, scan_tests=False) |
|
93 m = m.get_harness_options_manifest(False) |
|
94 reqs = m["five/main"]["requirements"] |
|
95 self.failUnlessEqual(reqs, {}); |
|
96 |
|
97 def test_unreachable_relative_main_in_top(self): |
|
98 target_cfg = self.get_pkg("six") |
|
99 package_path = [] |
|
100 pkg_cfg = packaging.build_config(ROOT, target_cfg, |
|
101 packagepath=package_path) |
|
102 deps = packaging.get_deps_for_targets(pkg_cfg, |
|
103 [target_cfg.name, "addon-sdk"]) |
|
104 self.failUnlessEqual(deps, ["addon-sdk", "six"]) |
|
105 self.assertRaises(manifest.UnreachablePrefixError, |
|
106 manifest.build_manifest, |
|
107 target_cfg, pkg_cfg, deps, scan_tests=False) |
|
108 |
|
109 def test_unreachable_in_deps(self): |
|
110 target_cfg = self.get_pkg("four") |
|
111 package_path = [get_linker_files_dir("four-deps")] |
|
112 pkg_cfg = packaging.build_config(ROOT, target_cfg, |
|
113 packagepath=package_path) |
|
114 deps = packaging.get_deps_for_targets(pkg_cfg, |
|
115 [target_cfg.name, "addon-sdk"]) |
|
116 self.failUnlessEqual(deps, ["addon-sdk", "four"]) |
|
117 self.assertRaises(manifest.UnreachablePrefixError, |
|
118 manifest.build_manifest, |
|
119 target_cfg, pkg_cfg, deps, scan_tests=False) |
|
120 |
|
121 class Contents(unittest.TestCase): |
|
122 |
|
123 def run_in_subdir(self, dirname, f, *args, **kwargs): |
|
124 top = os.path.abspath(os.getcwd()) |
|
125 basedir = os.path.abspath(os.path.join(".test_tmp",self.id(),dirname)) |
|
126 if os.path.isdir(basedir): |
|
127 assert basedir.startswith(top) |
|
128 shutil.rmtree(basedir) |
|
129 os.makedirs(basedir) |
|
130 try: |
|
131 os.chdir(basedir) |
|
132 return f(basedir, *args, **kwargs) |
|
133 finally: |
|
134 os.chdir(top) |
|
135 |
|
136 def assertIn(self, what, inside_what): |
|
137 self.failUnless(what in inside_what, inside_what) |
|
138 |
|
139 def test_jetpackID(self): |
|
140 # this uses "id": "jid7", to which a @jetpack should be appended |
|
141 seven = get_linker_files_dir("seven") |
|
142 def _test(basedir): |
|
143 stdout = StringIO() |
|
144 shutil.copytree(seven, "seven") |
|
145 os.chdir("seven") |
|
146 try: |
|
147 # regrettably, run() always finishes with sys.exit() |
|
148 cuddlefish.run(["xpi", "--no-strip-xpi"], |
|
149 stdout=stdout) |
|
150 except SystemExit, e: |
|
151 self.failUnlessEqual(e.args[0], 0) |
|
152 zf = zipfile.ZipFile("seven.xpi", "r") |
|
153 hopts = json.loads(zf.read("harness-options.json")) |
|
154 self.failUnlessEqual(hopts["jetpackID"], "jid7@jetpack") |
|
155 self.run_in_subdir("x", _test) |
|
156 |
|
157 def test_jetpackID_suffix(self): |
|
158 # this uses "id": "jid1@jetpack", so no suffix should be appended |
|
159 one = get_linker_files_dir("one") |
|
160 def _test(basedir): |
|
161 stdout = StringIO() |
|
162 shutil.copytree(one, "one") |
|
163 os.chdir("one") |
|
164 try: |
|
165 # regrettably, run() always finishes with sys.exit() |
|
166 cuddlefish.run(["xpi", "--no-strip-xpi"], |
|
167 stdout=stdout) |
|
168 except SystemExit, e: |
|
169 self.failUnlessEqual(e.args[0], 0) |
|
170 zf = zipfile.ZipFile("one.xpi", "r") |
|
171 hopts = json.loads(zf.read("harness-options.json")) |
|
172 self.failUnlessEqual(hopts["jetpackID"], "jid1@jetpack") |
|
173 self.run_in_subdir("x", _test) |
|
174 |
|
175 def test_strip_default(self): |
|
176 seven = get_linker_files_dir("seven") |
|
177 # now run 'cfx xpi' in that directory, except put the generated .xpi |
|
178 # elsewhere |
|
179 def _test(basedir): |
|
180 stdout = StringIO() |
|
181 shutil.copytree(seven, "seven") |
|
182 os.chdir("seven") |
|
183 try: |
|
184 # regrettably, run() always finishes with sys.exit() |
|
185 cuddlefish.run(["xpi"], # --strip-xpi is now the default |
|
186 stdout=stdout) |
|
187 except SystemExit, e: |
|
188 self.failUnlessEqual(e.args[0], 0) |
|
189 zf = zipfile.ZipFile("seven.xpi", "r") |
|
190 names = zf.namelist() |
|
191 # problem found in bug 664840 was that an addon |
|
192 # without an explicit tests/ directory would copy all files from |
|
193 # the package into a bogus JID-PKGNAME-tests/ directory, so check |
|
194 # for that |
|
195 testfiles = [fn for fn in names if "seven/tests" in fn] |
|
196 self.failUnlessEqual([], testfiles) |
|
197 # another problem was that data files were being stripped from |
|
198 # the XPI. Note that data/ is only supposed to be included if a |
|
199 # module that actually gets used does a require("self") . |
|
200 self.assertIn("resources/seven/data/text.data", |
|
201 names) |
|
202 self.failIf("seven/lib/unused.js" |
|
203 in names, names) |
|
204 self.run_in_subdir("x", _test) |
|
205 |
|
206 def test_no_strip(self): |
|
207 seven = get_linker_files_dir("seven") |
|
208 def _test(basedir): |
|
209 stdout = StringIO() |
|
210 shutil.copytree(seven, "seven") |
|
211 os.chdir("seven") |
|
212 try: |
|
213 # regrettably, run() always finishes with sys.exit() |
|
214 cuddlefish.run(["xpi", "--no-strip-xpi"], |
|
215 stdout=stdout) |
|
216 except SystemExit, e: |
|
217 self.failUnlessEqual(e.args[0], 0) |
|
218 zf = zipfile.ZipFile("seven.xpi", "r") |
|
219 names = zf.namelist() |
|
220 self.assertIn("resources/addon-sdk/lib/sdk/loader/cuddlefish.js", names) |
|
221 testfiles = [fn for fn in names if "seven/tests" in fn] |
|
222 self.failUnlessEqual([], testfiles) |
|
223 self.assertIn("resources/seven/data/text.data", |
|
224 names) |
|
225 self.failUnless("resources/seven/lib/unused.js" |
|
226 in names, names) |
|
227 self.run_in_subdir("x", _test) |
|
228 |
|
229 |
|
230 if __name__ == '__main__': |
|
231 unittest.main() |