parse.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. # ex:ts=4:sw=4:sts=4:et
  2. # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
  3. #
  4. # BitBake Test for lib/bb/parse/
  5. #
  6. # Copyright (C) 2015 Richard Purdie
  7. #
  8. # SPDX-License-Identifier: GPL-2.0-only
  9. #
  10. import unittest
  11. import tempfile
  12. import logging
  13. import bb
  14. import os
  15. logger = logging.getLogger('BitBake.TestParse')
  16. import bb.parse
  17. import bb.data
  18. import bb.siggen
  19. class ParseTest(unittest.TestCase):
  20. testfile = """
  21. A = "1"
  22. B = "2"
  23. do_install() {
  24. echo "hello"
  25. }
  26. C = "3"
  27. """
  28. def setUp(self):
  29. self.origdir = os.getcwd()
  30. self.d = bb.data.init()
  31. bb.parse.siggen = bb.siggen.init(self.d)
  32. def tearDown(self):
  33. os.chdir(self.origdir)
  34. def parsehelper(self, content, suffix = ".bb"):
  35. f = tempfile.NamedTemporaryFile(suffix = suffix)
  36. f.write(bytes(content, "utf-8"))
  37. f.flush()
  38. os.chdir(os.path.dirname(f.name))
  39. return f
  40. def test_parse_simple(self):
  41. f = self.parsehelper(self.testfile)
  42. d = bb.parse.handle(f.name, self.d)['']
  43. self.assertEqual(d.getVar("A"), "1")
  44. self.assertEqual(d.getVar("B"), "2")
  45. self.assertEqual(d.getVar("C"), "3")
  46. def test_parse_incomplete_function(self):
  47. testfileB = self.testfile.replace("}", "")
  48. f = self.parsehelper(testfileB)
  49. with self.assertRaises(bb.parse.ParseError):
  50. d = bb.parse.handle(f.name, self.d)['']
  51. unsettest = """
  52. A = "1"
  53. B = "2"
  54. B[flag] = "3"
  55. unset A
  56. unset B[flag]
  57. """
  58. def test_parse_unset(self):
  59. f = self.parsehelper(self.unsettest)
  60. d = bb.parse.handle(f.name, self.d)['']
  61. self.assertEqual(d.getVar("A"), None)
  62. self.assertEqual(d.getVarFlag("A","flag"), None)
  63. self.assertEqual(d.getVar("B"), "2")
  64. exporttest = """
  65. A = "a"
  66. export B = "b"
  67. export C
  68. exportD = "d"
  69. """
  70. def test_parse_exports(self):
  71. f = self.parsehelper(self.exporttest)
  72. d = bb.parse.handle(f.name, self.d)['']
  73. self.assertEqual(d.getVar("A"), "a")
  74. self.assertIsNone(d.getVarFlag("A", "export"))
  75. self.assertEqual(d.getVar("B"), "b")
  76. self.assertEqual(d.getVarFlag("B", "export"), 1)
  77. self.assertIsNone(d.getVar("C"))
  78. self.assertEqual(d.getVarFlag("C", "export"), 1)
  79. self.assertIsNone(d.getVar("D"))
  80. self.assertIsNone(d.getVarFlag("D", "export"))
  81. self.assertEqual(d.getVar("exportD"), "d")
  82. self.assertIsNone(d.getVarFlag("exportD", "export"))
  83. overridetest = """
  84. RRECOMMENDS_${PN} = "a"
  85. RRECOMMENDS_${PN}_libc = "b"
  86. OVERRIDES = "libc:${PN}"
  87. PN = "gtk+"
  88. """
  89. def test_parse_overrides(self):
  90. f = self.parsehelper(self.overridetest)
  91. d = bb.parse.handle(f.name, self.d)['']
  92. self.assertEqual(d.getVar("RRECOMMENDS"), "b")
  93. bb.data.expandKeys(d)
  94. self.assertEqual(d.getVar("RRECOMMENDS"), "b")
  95. d.setVar("RRECOMMENDS_gtk+", "c")
  96. self.assertEqual(d.getVar("RRECOMMENDS"), "c")
  97. overridetest2 = """
  98. EXTRA_OECONF = ""
  99. EXTRA_OECONF_class-target = "b"
  100. EXTRA_OECONF_append = " c"
  101. """
  102. def test_parse_overrides(self):
  103. f = self.parsehelper(self.overridetest2)
  104. d = bb.parse.handle(f.name, self.d)['']
  105. d.appendVar("EXTRA_OECONF", " d")
  106. d.setVar("OVERRIDES", "class-target")
  107. self.assertEqual(d.getVar("EXTRA_OECONF"), "b c d")
  108. overridetest3 = """
  109. DESCRIPTION = "A"
  110. DESCRIPTION_${PN}-dev = "${DESCRIPTION} B"
  111. PN = "bc"
  112. """
  113. def test_parse_combinations(self):
  114. f = self.parsehelper(self.overridetest3)
  115. d = bb.parse.handle(f.name, self.d)['']
  116. bb.data.expandKeys(d)
  117. self.assertEqual(d.getVar("DESCRIPTION_bc-dev"), "A B")
  118. d.setVar("DESCRIPTION", "E")
  119. d.setVar("DESCRIPTION_bc-dev", "C D")
  120. d.setVar("OVERRIDES", "bc-dev")
  121. self.assertEqual(d.getVar("DESCRIPTION"), "C D")
  122. classextend = """
  123. VAR_var_override1 = "B"
  124. EXTRA = ":override1"
  125. OVERRIDES = "nothing${EXTRA}"
  126. BBCLASSEXTEND = "###CLASS###"
  127. """
  128. classextend_bbclass = """
  129. EXTRA = ""
  130. python () {
  131. d.renameVar("VAR_var", "VAR_var2")
  132. }
  133. """
  134. #
  135. # Test based upon a real world data corruption issue. One
  136. # data store changing a variable poked through into a different data
  137. # store. This test case replicates that issue where the value 'B' would
  138. # become unset/disappear.
  139. #
  140. def test_parse_classextend_contamination(self):
  141. cls = self.parsehelper(self.classextend_bbclass, suffix=".bbclass")
  142. #clsname = os.path.basename(cls.name).replace(".bbclass", "")
  143. self.classextend = self.classextend.replace("###CLASS###", cls.name)
  144. f = self.parsehelper(self.classextend)
  145. alldata = bb.parse.handle(f.name, self.d)
  146. d1 = alldata['']
  147. d2 = alldata[cls.name]
  148. self.assertEqual(d1.getVar("VAR_var"), "B")
  149. self.assertEqual(d2.getVar("VAR_var"), None)
  150. addtask_deltask = """
  151. addtask do_patch after do_foo after do_unpack before do_configure before do_compile
  152. addtask do_fetch do_patch
  153. deltask do_fetch do_patch
  154. """
  155. def test_parse_addtask_deltask(self):
  156. import sys
  157. f = self.parsehelper(self.addtask_deltask)
  158. d = bb.parse.handle(f.name, self.d)['']
  159. stdout = sys.stdout.getvalue()
  160. self.assertTrue("addtask contained multiple 'before' keywords" in stdout)
  161. self.assertTrue("addtask contained multiple 'after' keywords" in stdout)
  162. self.assertTrue('addtask ignored: " do_patch"' in stdout)
  163. self.assertTrue('deltask ignored: " do_patch"' in stdout)
  164. #self.assertTrue('dependent task do_foo for do_patch does not exist' in stdout)