xref: /OK3568_Linux_fs/yocto/poky/bitbake/lib/toaster/tests/builds/buildtest.py (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#! /usr/bin/env python3
2*4882a593Smuzhiyun#
3*4882a593Smuzhiyun# BitBake Toaster Implementation
4*4882a593Smuzhiyun#
5*4882a593Smuzhiyun# Copyright (C) 2016 Intel Corporation
6*4882a593Smuzhiyun#
7*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only
8*4882a593Smuzhiyun#
9*4882a593Smuzhiyun
10*4882a593Smuzhiyunimport os
11*4882a593Smuzhiyunimport sys
12*4882a593Smuzhiyunimport time
13*4882a593Smuzhiyunimport unittest
14*4882a593Smuzhiyun
15*4882a593Smuzhiyunfrom orm.models import Project, Release, ProjectTarget, Build, ProjectVariable
16*4882a593Smuzhiyunfrom bldcontrol.models import BuildEnvironment
17*4882a593Smuzhiyun
18*4882a593Smuzhiyunfrom bldcontrol.management.commands.runbuilds import Command\
19*4882a593Smuzhiyun    as RunBuildsCommand
20*4882a593Smuzhiyun
21*4882a593Smuzhiyunfrom django.core.management import call_command
22*4882a593Smuzhiyun
23*4882a593Smuzhiyunimport subprocess
24*4882a593Smuzhiyunimport logging
25*4882a593Smuzhiyun
26*4882a593Smuzhiyunlogger = logging.getLogger("toaster")
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun# We use unittest.TestCase instead of django.test.TestCase because we don't
29*4882a593Smuzhiyun# want to wrap everything in a database transaction as an external process
30*4882a593Smuzhiyun# (bitbake needs access to the database)
31*4882a593Smuzhiyun
32*4882a593Smuzhiyundef load_build_environment():
33*4882a593Smuzhiyun    call_command('loaddata', 'settings.xml', app_label="orm")
34*4882a593Smuzhiyun    call_command('loaddata', 'poky.xml', app_label="orm")
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun    current_builddir = os.environ.get("BUILDDIR")
37*4882a593Smuzhiyun    if current_builddir:
38*4882a593Smuzhiyun        BuildTest.BUILDDIR = current_builddir
39*4882a593Smuzhiyun    else:
40*4882a593Smuzhiyun        # Setup a builddir based on default layout
41*4882a593Smuzhiyun        # bitbake inside openebedded-core
42*4882a593Smuzhiyun        oe_init_build_env_path = os.path.join(
43*4882a593Smuzhiyun            os.path.dirname(os.path.abspath(__file__)),
44*4882a593Smuzhiyun            os.pardir,
45*4882a593Smuzhiyun            os.pardir,
46*4882a593Smuzhiyun            os.pardir,
47*4882a593Smuzhiyun            os.pardir,
48*4882a593Smuzhiyun            os.pardir,
49*4882a593Smuzhiyun            'oe-init-build-env'
50*4882a593Smuzhiyun        )
51*4882a593Smuzhiyun        if not os.path.exists(oe_init_build_env_path):
52*4882a593Smuzhiyun            raise Exception("We had no BUILDDIR set and couldn't "
53*4882a593Smuzhiyun                            "find oe-init-build-env to set this up "
54*4882a593Smuzhiyun                            "ourselves please run oe-init-build-env "
55*4882a593Smuzhiyun                            "before running these tests")
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun        oe_init_build_env_path = os.path.realpath(oe_init_build_env_path)
58*4882a593Smuzhiyun        cmd = "bash -c 'source oe-init-build-env %s'" % BuildTest.BUILDDIR
59*4882a593Smuzhiyun        p = subprocess.Popen(
60*4882a593Smuzhiyun            cmd,
61*4882a593Smuzhiyun            cwd=os.path.dirname(oe_init_build_env_path),
62*4882a593Smuzhiyun            shell=True,
63*4882a593Smuzhiyun            stdout=subprocess.PIPE,
64*4882a593Smuzhiyun            stderr=subprocess.PIPE)
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun        output, err = p.communicate()
67*4882a593Smuzhiyun        p.wait()
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun        logger.info("oe-init-build-env %s %s" % (output, err))
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun        os.environ['BUILDDIR'] = BuildTest.BUILDDIR
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun    # Setup the path to bitbake we know where to find this
74*4882a593Smuzhiyun    bitbake_path = os.path.join(
75*4882a593Smuzhiyun        os.path.dirname(os.path.abspath(__file__)),
76*4882a593Smuzhiyun        os.pardir,
77*4882a593Smuzhiyun        os.pardir,
78*4882a593Smuzhiyun        os.pardir,
79*4882a593Smuzhiyun        os.pardir,
80*4882a593Smuzhiyun        'bin',
81*4882a593Smuzhiyun        'bitbake')
82*4882a593Smuzhiyun    if not os.path.exists(bitbake_path):
83*4882a593Smuzhiyun        raise Exception("Could not find bitbake at the expected path %s"
84*4882a593Smuzhiyun                        % bitbake_path)
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun    os.environ['BBBASEDIR'] = bitbake_path
87*4882a593Smuzhiyun
88*4882a593Smuzhiyunclass BuildTest(unittest.TestCase):
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun    PROJECT_NAME = "Testbuild"
91*4882a593Smuzhiyun    BUILDDIR = "/tmp/build/"
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun    def build(self, target):
94*4882a593Smuzhiyun        # So that the buildinfo helper uses the test database'
95*4882a593Smuzhiyun        self.assertEqual(
96*4882a593Smuzhiyun            os.environ.get('DJANGO_SETTINGS_MODULE', ''),
97*4882a593Smuzhiyun            'toastermain.settings_test',
98*4882a593Smuzhiyun            "Please initialise django with the tests settings:  "
99*4882a593Smuzhiyun            "DJANGO_SETTINGS_MODULE='toastermain.settings_test'")
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun        built = self.target_already_built(target)
102*4882a593Smuzhiyun        if built:
103*4882a593Smuzhiyun            return built
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun        load_build_environment()
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun        BuildEnvironment.objects.get_or_create(
108*4882a593Smuzhiyun            betype=BuildEnvironment.TYPE_LOCAL,
109*4882a593Smuzhiyun            sourcedir=BuildTest.BUILDDIR,
110*4882a593Smuzhiyun            builddir=BuildTest.BUILDDIR
111*4882a593Smuzhiyun        )
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun        release = Release.objects.get(name='local')
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun        # Create a project for this build to run in
116*4882a593Smuzhiyun        project = Project.objects.create_project(name=BuildTest.PROJECT_NAME,
117*4882a593Smuzhiyun                                                 release=release)
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun        if os.environ.get("TOASTER_TEST_USE_SSTATE_MIRROR"):
120*4882a593Smuzhiyun            ProjectVariable.objects.get_or_create(
121*4882a593Smuzhiyun                name="SSTATE_MIRRORS",
122*4882a593Smuzhiyun                value="file://.* http://sstate.yoctoproject.org/PATH;downloadfilename=PATH",
123*4882a593Smuzhiyun                project=project)
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun        ProjectTarget.objects.create(project=project,
126*4882a593Smuzhiyun                                     target=target,
127*4882a593Smuzhiyun                                     task="")
128*4882a593Smuzhiyun        build_request = project.schedule_build()
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun        # run runbuilds command to dispatch the build
131*4882a593Smuzhiyun        # e.g. manage.py runubilds
132*4882a593Smuzhiyun        RunBuildsCommand().runbuild()
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun        build_pk = build_request.build.pk
135*4882a593Smuzhiyun        while Build.objects.get(pk=build_pk).outcome == Build.IN_PROGRESS:
136*4882a593Smuzhiyun            sys.stdout.write("\rBuilding %s %d%%" %
137*4882a593Smuzhiyun                             (target,
138*4882a593Smuzhiyun                              build_request.build.completeper()))
139*4882a593Smuzhiyun            sys.stdout.flush()
140*4882a593Smuzhiyun            time.sleep(1)
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun        self.assertEqual(Build.objects.get(pk=build_pk).outcome,
143*4882a593Smuzhiyun                         Build.SUCCEEDED,
144*4882a593Smuzhiyun                         "Build did not SUCCEEDED")
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun        logger.info("\nBuild finished %s" % build_request.build.outcome)
147*4882a593Smuzhiyun        return build_request.build
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun    def target_already_built(self, target):
150*4882a593Smuzhiyun        """ If the target is already built no need to build it again"""
151*4882a593Smuzhiyun        for build in Build.objects.filter(
152*4882a593Smuzhiyun                project__name=BuildTest.PROJECT_NAME):
153*4882a593Smuzhiyun            targets = build.target_set.values_list('target', flat=True)
154*4882a593Smuzhiyun            if target in targets:
155*4882a593Smuzhiyun                return build
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun        return None
158