test_linker.py 10 KB

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