blob: 5a56a110a74fe54fef305b4470f943b1e87708f7 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001#! /usr/bin/env python
2# ex:ts=4:sw=4:sts=4:et
3# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
4#
5# BitBake Toaster Implementation
6#
7# Copyright (C) 2016 Intel Corporation
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License version 2 as
11# published by the Free Software Foundation.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License along
19# with this program; if not, write to the Free Software Foundation, Inc.,
20# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
22import os
23import sys
24import time
25import unittest
26
27from orm.models import Project, Release, ProjectTarget, Build, ProjectVariable
28from bldcontrol.models import BuildEnvironment
29
30from bldcontrol.management.commands.runbuilds import Command\
31 as RunBuildsCommand
32
33from django.core.management import call_command
34
35import subprocess
36import logging
37
38logger = logging.getLogger("toaster")
39
40# We use unittest.TestCase instead of django.test.TestCase because we don't
41# want to wrap everything in a database transaction as an external process
42# (bitbake needs access to the database)
43
44def load_build_environment():
45 call_command('loaddata', 'settings.xml', app_label="orm")
46 call_command('loaddata', 'poky.xml', app_label="orm")
47
48 current_builddir = os.environ.get("BUILDDIR")
49 if current_builddir:
50 BuildTest.BUILDDIR = current_builddir
51 else:
52 # Setup a builddir based on default layout
53 # bitbake inside openebedded-core
54 oe_init_build_env_path = os.path.join(
55 os.path.dirname(os.path.abspath(__file__)),
56 os.pardir,
57 os.pardir,
58 os.pardir,
59 os.pardir,
60 os.pardir,
61 'oe-init-build-env'
62 )
63 if not os.path.exists(oe_init_build_env_path):
64 raise Exception("We had no BUILDDIR set and couldn't "
65 "find oe-init-build-env to set this up "
66 "ourselves please run oe-init-build-env "
67 "before running these tests")
68
69 oe_init_build_env_path = os.path.realpath(oe_init_build_env_path)
70 cmd = "bash -c 'source oe-init-build-env %s'" % BuildTest.BUILDDIR
71 p = subprocess.Popen(
72 cmd,
73 cwd=os.path.dirname(oe_init_build_env_path),
74 shell=True,
75 stdout=subprocess.PIPE,
76 stderr=subprocess.PIPE)
77
78 output, err = p.communicate()
79 p.wait()
80
81 logger.info("oe-init-build-env %s %s" % (output, err))
82
83 os.environ['BUILDDIR'] = BuildTest.BUILDDIR
84
85 # Setup the path to bitbake we know where to find this
86 bitbake_path = os.path.join(
87 os.path.dirname(os.path.abspath(__file__)),
88 os.pardir,
89 os.pardir,
90 os.pardir,
91 os.pardir,
92 'bin',
93 'bitbake')
94 if not os.path.exists(bitbake_path):
95 raise Exception("Could not find bitbake at the expected path %s"
96 % bitbake_path)
97
98 os.environ['BBBASEDIR'] = bitbake_path
99
100class BuildTest(unittest.TestCase):
101
102 PROJECT_NAME = "Testbuild"
103 BUILDDIR = "/tmp/build/"
104
105 def build(self, target):
106 # So that the buildinfo helper uses the test database'
107 self.assertEqual(
108 os.environ.get('DJANGO_SETTINGS_MODULE', ''),
109 'toastermain.settings_test',
110 "Please initialise django with the tests settings: "
111 "DJANGO_SETTINGS_MODULE='toastermain.settings_test'")
112
113 built = self.target_already_built(target)
114 if built:
115 return built
116
117 load_build_environment()
118
119 BuildEnvironment.objects.get_or_create(
120 betype=BuildEnvironment.TYPE_LOCAL,
121 sourcedir=BuildTest.BUILDDIR,
122 builddir=BuildTest.BUILDDIR
123 )
124
125 release = Release.objects.get(name='local')
126
127 # Create a project for this build to run in
128 project = Project.objects.create_project(name=BuildTest.PROJECT_NAME,
129 release=release)
130
131 if os.environ.get("TOASTER_TEST_USE_SSTATE_MIRROR"):
132 ProjectVariable.objects.get_or_create(
133 name="SSTATE_MIRRORS",
134 value="file://.* http://autobuilder.yoctoproject.org/pub/sstate/PATH;downloadfilename=PATH",
135 project=project)
136
137 ProjectTarget.objects.create(project=project,
138 target=target,
139 task="")
140 build_request = project.schedule_build()
141
142 # run runbuilds command to dispatch the build
143 # e.g. manage.py runubilds
144 RunBuildsCommand().runbuild()
145
146 build_pk = build_request.build.pk
147 while Build.objects.get(pk=build_pk).outcome == Build.IN_PROGRESS:
148 sys.stdout.write("\rBuilding %s %d%%" %
149 (target,
150 build_request.build.completeper()))
151 sys.stdout.flush()
152 time.sleep(1)
153
154 self.assertEqual(Build.objects.get(pk=build_pk).outcome,
155 Build.SUCCEEDED,
156 "Build did not SUCCEEDED")
157
158 logger.info("\nBuild finished %s" % build_request.build.outcome)
159 return build_request.build
160
161 def target_already_built(self, target):
162 """ If the target is already built no need to build it again"""
163 for build in Build.objects.filter(
164 project__name=BuildTest.PROJECT_NAME):
165 targets = build.target_set.values_list('target', flat=True)
166 if target in targets:
167 return build
168
169 return None