diff options
| author | Alexander Kanavin <alex@linutronix.de> | 2025-09-29 14:56:08 +0200 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2025-10-04 11:16:43 +0100 |
| commit | ec7c31497d261f0b8973e8d8aee876775b89b153 (patch) | |
| tree | 4f7cd076620c9a2b0aace5a91e4bb7e8917f39f1 | |
| parent | 5e0593f116b351d7981175dc63af1ff0e123a2d6 (diff) | |
| download | poky-ec7c31497d261f0b8973e8d8aee876775b89b153.tar.gz | |
bitbake: bitbake-setup: add tests to bitbake-selftest
Run like this:
alex@Zen2:/srv/work/alex/bitbake$ bin/bitbake-selftest -v bb.tests.setup
test_setup (bb.tests.setup.BitbakeSetupTest.test_setup) ... ok
----------------------------------------------------------------------
Ran 1 test in 9.223s
OK
The test does a basic run-through of init, then status/update
on an unchanged configuration, then status/update on a
configuration changed via new commits to the test layer,
then status/update on configuration changed via the top
level json config file.
Note that nothing whatsoever is fetched from the network;
the test relies entirely on synthetic data contained inside
itself, including minimal stubs for oe-setup-build and
bitbake-config-build. This data is used to create temporary
git repositories then clone them via local filesystem URIs.
Later on this can be supplemented by an oe-selftest that
tests bitbake-setup against real config files in the
official configuration repository and real layers,
templates and fragments.
(Bitbake rev: 59ec7e2ac56e364bae39ccb5e884c447a5379531)
Signed-off-by: Alexander Kanavin <alex@linutronix.de>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
| -rwxr-xr-x | bitbake/bin/bitbake-selftest | 1 | ||||
| -rw-r--r-- | bitbake/lib/bb/tests/setup.py | 266 |
2 files changed, 267 insertions, 0 deletions
diff --git a/bitbake/bin/bitbake-selftest b/bitbake/bin/bitbake-selftest index d45c2d406d..fb7c57dd83 100755 --- a/bitbake/bin/bitbake-selftest +++ b/bitbake/bin/bitbake-selftest | |||
| @@ -29,6 +29,7 @@ tests = ["bb.tests.codeparser", | |||
| 29 | "bb.tests.fetch", | 29 | "bb.tests.fetch", |
| 30 | "bb.tests.parse", | 30 | "bb.tests.parse", |
| 31 | "bb.tests.runqueue", | 31 | "bb.tests.runqueue", |
| 32 | "bb.tests.setup", | ||
| 32 | "bb.tests.siggen", | 33 | "bb.tests.siggen", |
| 33 | "bb.tests.utils", | 34 | "bb.tests.utils", |
| 34 | "bb.tests.compression", | 35 | "bb.tests.compression", |
diff --git a/bitbake/lib/bb/tests/setup.py b/bitbake/lib/bb/tests/setup.py new file mode 100644 index 0000000000..ab4dbf7621 --- /dev/null +++ b/bitbake/lib/bb/tests/setup.py | |||
| @@ -0,0 +1,266 @@ | |||
| 1 | # | ||
| 2 | # Copyright BitBake Contributors | ||
| 3 | # | ||
| 4 | # SPDX-License-Identifier: GPL-2.0-only | ||
| 5 | # | ||
| 6 | |||
| 7 | from bb.tests.fetch import FetcherTest | ||
| 8 | import json | ||
| 9 | |||
| 10 | class BitbakeSetupTest(FetcherTest): | ||
| 11 | def setUp(self): | ||
| 12 | super(BitbakeSetupTest, self).setUp() | ||
| 13 | |||
| 14 | self.registrypath = os.path.join(self.tempdir, "bitbake-setup-configurations") | ||
| 15 | |||
| 16 | os.makedirs(self.registrypath) | ||
| 17 | self.git_init(cwd=self.registrypath) | ||
| 18 | self.git('commit --allow-empty -m "Initial commit"', cwd=self.registrypath) | ||
| 19 | |||
| 20 | self.testrepopath = os.path.join(self.tempdir, "test-repo") | ||
| 21 | os.makedirs(self.testrepopath) | ||
| 22 | self.git_init(cwd=self.testrepopath) | ||
| 23 | self.git('commit --allow-empty -m "Initial commit"', cwd=self.testrepopath) | ||
| 24 | |||
| 25 | oeinitbuildenv = """BBPATH=$1 | ||
| 26 | export BBPATH | ||
| 27 | PATH={}:$PATH | ||
| 28 | """.format(os.path.join(self.testrepopath, 'scripts')) | ||
| 29 | self.add_file_to_testrepo('oe-init-build-env',oeinitbuildenv, script=True) | ||
| 30 | |||
| 31 | oesetupbuild = """#!/usr/bin/env python3 | ||
| 32 | import getopt | ||
| 33 | import sys | ||
| 34 | import os | ||
| 35 | import shutil | ||
| 36 | opts, args = getopt.getopt(sys.argv[2:], "c:b:", ["no-shell"]) | ||
| 37 | for option, value in opts: | ||
| 38 | if option == '-c': | ||
| 39 | template = value | ||
| 40 | if option == '-b': | ||
| 41 | builddir = value | ||
| 42 | confdir = os.path.join(builddir, 'conf') | ||
| 43 | os.makedirs(confdir, exist_ok=True) | ||
| 44 | with open(os.path.join(confdir, 'conf-summary.txt'), 'w') as f: | ||
| 45 | f.write(template) | ||
| 46 | shutil.copy(os.path.join(os.path.dirname(__file__), 'test-repo/test-file'), confdir) | ||
| 47 | with open(os.path.join(builddir, 'init-build-env'), 'w') as f: | ||
| 48 | f.write("BBPATH={}\\nexport BBPATH\\nPATH={}:$PATH".format(builddir, os.path.join(os.path.dirname(__file__), 'test-repo/scripts'))) | ||
| 49 | """ | ||
| 50 | self.add_file_to_testrepo('scripts/oe-setup-build', oesetupbuild, script=True) | ||
| 51 | |||
| 52 | bitbakeconfigbuild = """#!/usr/bin/env python3 | ||
| 53 | import os | ||
| 54 | import sys | ||
| 55 | confdir = os.path.join(os.environ['BBPATH'], 'conf') | ||
| 56 | fragment = sys.argv[2] | ||
| 57 | with open(os.path.join(confdir, fragment), 'w') as f: | ||
| 58 | f.write('') | ||
| 59 | """ | ||
| 60 | self.add_file_to_testrepo('scripts/bitbake-config-build', bitbakeconfigbuild, script=True) | ||
| 61 | |||
| 62 | sometargetexecutable_template = """#!/usr/bin/env python3 | ||
| 63 | import os | ||
| 64 | print("This is {}") | ||
| 65 | print("BBPATH is {{}}".format(os.environ["BBPATH"])) | ||
| 66 | """ | ||
| 67 | for e_name in ("some-target-executable-1", "some-target-executable-2"): | ||
| 68 | sometargetexecutable = sometargetexecutable_template.format(e_name) | ||
| 69 | self.add_file_to_testrepo('scripts/{}'.format(e_name), sometargetexecutable, script=True) | ||
| 70 | |||
| 71 | def runbbsetup(self, cmd): | ||
| 72 | bbsetup = os.path.abspath(os.path.dirname(__file__) + "/../../../bin/bitbake-setup") | ||
| 73 | return bb.process.run("{} --global-settings {} {}".format(bbsetup, os.path.join(self.tempdir, 'global-config'), cmd)) | ||
| 74 | |||
| 75 | def add_json_config_to_registry(self, name, rev): | ||
| 76 | config = """ | ||
| 77 | { | ||
| 78 | "sources": { | ||
| 79 | "test-repo": { | ||
| 80 | "git-remote": { | ||
| 81 | "remotes": { | ||
| 82 | "origin": { | ||
| 83 | "uri": "file://%s" | ||
| 84 | } | ||
| 85 | }, | ||
| 86 | "rev": "%s" | ||
| 87 | }, | ||
| 88 | "path": "test-repo" | ||
| 89 | } | ||
| 90 | }, | ||
| 91 | "description": "Test configuration", | ||
| 92 | "bitbake-setup": { | ||
| 93 | "configurations": [ | ||
| 94 | { | ||
| 95 | "name": "gadget", | ||
| 96 | "description": "Gadget build configuration", | ||
| 97 | "oe-template": "test-configuration-gadget", | ||
| 98 | "oe-fragments": ["test-fragment-1"] | ||
| 99 | }, | ||
| 100 | { | ||
| 101 | "name": "gizmo", | ||
| 102 | "description": "Gizmo build configuration", | ||
| 103 | "oe-template": "test-configuration-gizmo", | ||
| 104 | "oe-fragments": ["test-fragment-2"] | ||
| 105 | }, | ||
| 106 | { | ||
| 107 | "name": "gadget-notemplate", | ||
| 108 | "description": "Gadget notemplate build configuration", | ||
| 109 | "bb-layers": ["layerA","layerB/meta-layer"], | ||
| 110 | "oe-fragments": ["test-fragment-1"] | ||
| 111 | }, | ||
| 112 | { | ||
| 113 | "name": "gizmo-notemplate", | ||
| 114 | "description": "Gizmo notemplate build configuration", | ||
| 115 | "bb-layers": ["layerC","layerD/meta-layer"], | ||
| 116 | "oe-fragments": ["test-fragment-2"] | ||
| 117 | } | ||
| 118 | ] | ||
| 119 | }, | ||
| 120 | "version": "1.0" | ||
| 121 | } | ||
| 122 | """ % (self.testrepopath, rev) | ||
| 123 | os.makedirs(os.path.join(self.registrypath, os.path.dirname(name)), exist_ok=True) | ||
| 124 | with open(os.path.join(self.registrypath, name), 'w') as f: | ||
| 125 | f.write(config) | ||
| 126 | self.git('add {}'.format(name), cwd=self.registrypath) | ||
| 127 | self.git('commit -m "Adding {}"'.format(name), cwd=self.registrypath) | ||
| 128 | return json.loads(config) | ||
| 129 | |||
| 130 | def add_file_to_testrepo(self, name, content, script=False): | ||
| 131 | fullname = os.path.join(self.testrepopath, name) | ||
| 132 | os.makedirs(os.path.join(self.testrepopath, os.path.dirname(name)), exist_ok=True) | ||
| 133 | with open(fullname, 'w') as f: | ||
| 134 | f.write(content) | ||
| 135 | if script: | ||
| 136 | import stat | ||
| 137 | st = os.stat(fullname) | ||
| 138 | os.chmod(fullname, st.st_mode | stat.S_IEXEC) | ||
| 139 | self.git('add {}'.format(name), cwd=self.testrepopath) | ||
| 140 | self.git('commit -m "Adding {}"'.format(name), cwd=self.testrepopath) | ||
| 141 | |||
| 142 | def check_builddir_files(self, buildpath, test_file_content, json_config): | ||
| 143 | with open(os.path.join(buildpath, 'layers', 'test-repo', 'test-file')) as f: | ||
| 144 | self.assertEqual(f.read(), test_file_content) | ||
| 145 | bitbake_config = json_config["bitbake-config"] | ||
| 146 | bb_build_path = os.path.join(buildpath, 'build') | ||
| 147 | bb_conf_path = os.path.join(bb_build_path, 'conf') | ||
| 148 | self.assertTrue(os.path.exists(os.path.join(bb_build_path, 'init-build-env'))) | ||
| 149 | |||
| 150 | if "oe-template" in bitbake_config: | ||
| 151 | with open(os.path.join(bb_conf_path, 'conf-summary.txt')) as f: | ||
| 152 | self.assertEqual(f.read(), bitbake_config["oe-template"]) | ||
| 153 | with open(os.path.join(bb_conf_path, 'test-file')) as f: | ||
| 154 | self.assertEqual(f.read(), test_file_content) | ||
| 155 | else: | ||
| 156 | with open(os.path.join(bb_conf_path, 'conf-summary.txt')) as f: | ||
| 157 | self.assertIn(bitbake_config["description"], f.read()) | ||
| 158 | with open(os.path.join(bb_conf_path, 'bblayers.conf')) as f: | ||
| 159 | bblayers = f.read() | ||
| 160 | for l in bitbake_config["bb-layers"]: | ||
| 161 | self.assertIn(os.path.join(buildpath, 'layers', l), bblayers) | ||
| 162 | |||
| 163 | for f in bitbake_config["oe-fragments"]: | ||
| 164 | self.assertTrue(os.path.exists(os.path.join(bb_conf_path, f))) | ||
| 165 | |||
| 166 | |||
| 167 | def test_setup(self): | ||
| 168 | # check that no arguments works | ||
| 169 | self.runbbsetup("") | ||
| 170 | |||
| 171 | # check that --help works | ||
| 172 | self.runbbsetup("--help") | ||
| 173 | |||
| 174 | # set up global location for top-dir-prefix | ||
| 175 | out = self.runbbsetup("install-global-settings") | ||
| 176 | settings_path = "{}/global-config".format(self.tempdir) | ||
| 177 | self.assertIn(settings_path, out[0]) | ||
| 178 | out = self.runbbsetup("change-global-setting default top-dir-prefix {}".format(self.tempdir)) | ||
| 179 | self.assertIn("Setting 'top-dir-prefix' in section 'default' is changed to", out[0]) | ||
| 180 | self.assertIn("New global settings written to".format(settings_path), out[0]) | ||
| 181 | |||
| 182 | # check that writing settings works and then adjust them to point to | ||
| 183 | # test registry repo | ||
| 184 | out = self.runbbsetup("install-settings") | ||
| 185 | settings_path = "{}/bitbake-builds/bitbake-setup.conf".format(self.tempdir) | ||
| 186 | self.assertIn(settings_path, out[0]) | ||
| 187 | out = self.runbbsetup("change-setting default registry 'git://{};protocol=file;branch=master;rev=master'".format(self.registrypath)) | ||
| 188 | self.assertIn("Setting 'registry' in section 'default' is changed to", out[0]) | ||
| 189 | self.assertIn("New settings written to".format(settings_path), out[0]) | ||
| 190 | |||
| 191 | # check that 'list' produces correct output with no configs, one config and two configs | ||
| 192 | out = self.runbbsetup("list") | ||
| 193 | self.assertNotIn("test-config-1", out[0]) | ||
| 194 | self.assertNotIn("test-config-2", out[0]) | ||
| 195 | |||
| 196 | json_1 = self.add_json_config_to_registry('test-config-1.conf.json', 'master') | ||
| 197 | out = self.runbbsetup("list") | ||
| 198 | self.assertIn("test-config-1", out[0]) | ||
| 199 | self.assertNotIn("test-config-2", out[0]) | ||
| 200 | |||
| 201 | json_2 = self.add_json_config_to_registry('config-2/test-config-2.conf.json', 'master') | ||
| 202 | out = self.runbbsetup("list --write-json={}".format(os.path.join(self.tempdir, "test-configs.json"))) | ||
| 203 | self.assertIn("test-config-1", out[0]) | ||
| 204 | self.assertIn("test-config-2", out[0]) | ||
| 205 | with open(os.path.join(self.tempdir, "test-configs.json")) as f: | ||
| 206 | json_configs = json.load(f) | ||
| 207 | self.assertIn("test-config-1", json_configs) | ||
| 208 | self.assertIn("test-config-2", json_configs) | ||
| 209 | |||
| 210 | # check that init/status/update work | ||
| 211 | # (the latter two should do nothing and say that config hasn't changed) | ||
| 212 | test_file_content = 'initial\n' | ||
| 213 | self.add_file_to_testrepo('test-file', test_file_content) | ||
| 214 | for cf in ('test-config-1', 'test-config-2'): | ||
| 215 | for c in ('gadget','gizmo','gadget-notemplate','gizmo-notemplate'): | ||
| 216 | out = self.runbbsetup("init --non-interactive {} {}".format(os.path.join(self.registrypath,'config-2/test-config-2.conf.json') if cf == 'test-config-2' else cf, c)) | ||
| 217 | buildpath = os.path.join(self.tempdir, 'bitbake-builds', '{}-{}'.format(cf, c)) | ||
| 218 | with open(os.path.join(buildpath, 'config', "config-upstream.json")) as f: | ||
| 219 | config_upstream = json.load(f) | ||
| 220 | self.check_builddir_files(buildpath, test_file_content, config_upstream) | ||
| 221 | os.environ['BBPATH'] = os.path.join(buildpath, 'build') | ||
| 222 | out = self.runbbsetup("status") | ||
| 223 | self.assertIn("Configuration in {} has not changed".format(buildpath), out[0]) | ||
| 224 | out = self.runbbsetup("update") | ||
| 225 | self.assertIn("Configuration in {} has not changed".format(buildpath), out[0]) | ||
| 226 | |||
| 227 | # change a file in the test layer repo, make a new commit and | ||
| 228 | # test that status/update correctly report the change and update the config | ||
| 229 | prev_test_file_content = test_file_content | ||
| 230 | test_file_content = 'modified\n' | ||
| 231 | self.add_file_to_testrepo('test-file', test_file_content) | ||
| 232 | for c in ('gadget','gizmo','gadget-notemplate','gizmo-notemplate'): | ||
| 233 | buildpath = os.path.join(self.tempdir, 'bitbake-builds', 'test-config-1-{}'.format(c)) | ||
| 234 | os.environ['BBPATH'] = os.path.join(buildpath, 'build') | ||
| 235 | out = self.runbbsetup("status") | ||
| 236 | self.assertIn("Layer repository file://{} checked out into {}/layers/test-repo updated revision master from".format(self.testrepopath, buildpath), out[0]) | ||
| 237 | out = self.runbbsetup("update") | ||
| 238 | if c in ('gadget','gizmo'): | ||
| 239 | self.assertIn("Existing bitbake configuration directory renamed to {}/build/conf-backup.".format(buildpath), out[0]) | ||
| 240 | self.assertIn('-{}+{}'.format(prev_test_file_content, test_file_content), out[0]) | ||
| 241 | with open(os.path.join(buildpath, 'config', "config-upstream.json")) as f: | ||
| 242 | config_upstream = json.load(f) | ||
| 243 | self.check_builddir_files(buildpath, test_file_content, config_upstream) | ||
| 244 | |||
| 245 | # make a new branch in the test layer repo, change a file on that branch, | ||
| 246 | # make a new commit, update the top level json config to refer to that branch, | ||
| 247 | # and test that status/update correctly report the change and update the config | ||
| 248 | prev_test_file_content = test_file_content | ||
| 249 | test_file_content = 'modified-in-branch\n' | ||
| 250 | branch = "another-branch" | ||
| 251 | self.git('checkout -b {}'.format(branch), cwd=self.testrepopath) | ||
| 252 | self.add_file_to_testrepo('test-file', test_file_content) | ||
| 253 | json_1 = self.add_json_config_to_registry('test-config-1.conf.json', branch) | ||
| 254 | for c in ('gadget','gizmo','gadget-notemplate','gizmo-notemplate'): | ||
| 255 | buildpath = os.path.join(self.tempdir, 'bitbake-builds', 'test-config-1-{}'.format(c)) | ||
| 256 | os.environ['BBPATH'] = os.path.join(buildpath, 'build') | ||
| 257 | out = self.runbbsetup("status") | ||
| 258 | self.assertIn("Configuration in {} has changed:".format(buildpath), out[0]) | ||
| 259 | self.assertIn('- "rev": "master"\n+ "rev": "another-branch"', out[0]) | ||
| 260 | out = self.runbbsetup("update") | ||
| 261 | if c in ('gadget','gizmo'): | ||
| 262 | self.assertIn("Existing bitbake configuration directory renamed to {}/build/conf-backup.".format(buildpath), out[0]) | ||
| 263 | self.assertIn('-{}+{}'.format(prev_test_file_content, test_file_content), out[0]) | ||
| 264 | with open(os.path.join(buildpath, 'config', "config-upstream.json")) as f: | ||
| 265 | config_upstream = json.load(f) | ||
| 266 | self.check_builddir_files(buildpath, test_file_content, config_upstream) | ||
