blob: 5a56a110a74fe54fef305b4470f943b1e87708f7 [file] [log] [blame]
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001#! /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
Brad Bishop6e60e8b2018-02-01 10:27:11 -050027from orm.models import Project, Release, ProjectTarget, Build, ProjectVariable
Patrick Williamsc0f7c042017-02-23 20:41:17 -060028from bldcontrol.models import BuildEnvironment
29
Patrick Williamsc0f7c042017-02-23 20:41:17 -060030from bldcontrol.management.commands.runbuilds import Command\
31 as RunBuildsCommand
32
Brad Bishop6e60e8b2018-02-01 10:27:11 -050033from django.core.management import call_command
34
Patrick Williamsc0f7c042017-02-23 20:41:17 -060035import subprocess
Brad Bishop6e60e8b2018-02-01 10:27:11 -050036import logging
37
38logger = logging.getLogger("toaster")
Patrick Williamsc0f7c042017-02-23 20:41:17 -060039
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
Brad Bishop6e60e8b2018-02-01 10:27:11 -050044def 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
Patrick Williamsc0f7c042017-02-23 20:41:17 -060099
100class BuildTest(unittest.TestCase):
101
102 PROJECT_NAME = "Testbuild"
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500103 BUILDDIR = "/tmp/build/"
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600104
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', ''),
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500109 'toastermain.settings_test',
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600110 "Please initialise django with the tests settings: "
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500111 "DJANGO_SETTINGS_MODULE='toastermain.settings_test'")
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600112
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500113 built = self.target_already_built(target)
114 if built:
115 return built
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600116
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500117 load_build_environment()
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600118
119 BuildEnvironment.objects.get_or_create(
120 betype=BuildEnvironment.TYPE_LOCAL,
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500121 sourcedir=BuildTest.BUILDDIR,
122 builddir=BuildTest.BUILDDIR
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600123 )
124
125 release = Release.objects.get(name='local')
126
127 # Create a project for this build to run in
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500128 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)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600136
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
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500154 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)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600159 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:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500167 return build
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600168
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500169 return None