1*ef83aea0SPhilippe Mathieu-Daudé#!/usr/bin/env python3 2*ef83aea0SPhilippe Mathieu-Daudé# 3*ef83aea0SPhilippe Mathieu-Daudé# Functional test that boots a Linux kernel and checks the console 4*ef83aea0SPhilippe Mathieu-Daudé# 5*ef83aea0SPhilippe Mathieu-Daudé# Copyright (c) 2020 Red Hat, Inc. 6*ef83aea0SPhilippe Mathieu-Daudé# 7*ef83aea0SPhilippe Mathieu-Daudé# Author: 8*ef83aea0SPhilippe Mathieu-Daudé# Thomas Huth <thuth@redhat.com> 9*ef83aea0SPhilippe Mathieu-Daudé# 10*ef83aea0SPhilippe Mathieu-Daudé# This work is licensed under the terms of the GNU GPL, version 2 or 11*ef83aea0SPhilippe Mathieu-Daudé# later. See the COPYING file in the top-level directory. 12*ef83aea0SPhilippe Mathieu-Daudé# 13*ef83aea0SPhilippe Mathieu-Daudé# SPDX-License-Identifier: GPL-2.0-or-later 14*ef83aea0SPhilippe Mathieu-Daudé 15*ef83aea0SPhilippe Mathieu-Daudéimport os 16*ef83aea0SPhilippe Mathieu-Daudéimport logging 17*ef83aea0SPhilippe Mathieu-Daudé 18*ef83aea0SPhilippe Mathieu-Daudéfrom qemu_test import QemuSystemTest, Asset 19*ef83aea0SPhilippe Mathieu-Daudéfrom qemu_test import wait_for_console_pattern 20*ef83aea0SPhilippe Mathieu-Daudéfrom unittest import skipUnless 21*ef83aea0SPhilippe Mathieu-Daudé 22*ef83aea0SPhilippe Mathieu-Daudé 23*ef83aea0SPhilippe Mathieu-DaudéNUMPY_AVAILABLE = True 24*ef83aea0SPhilippe Mathieu-Daudétry: 25*ef83aea0SPhilippe Mathieu-Daudé import numpy as np 26*ef83aea0SPhilippe Mathieu-Daudéexcept ImportError: 27*ef83aea0SPhilippe Mathieu-Daudé NUMPY_AVAILABLE = False 28*ef83aea0SPhilippe Mathieu-Daudé 29*ef83aea0SPhilippe Mathieu-DaudéCV2_AVAILABLE = True 30*ef83aea0SPhilippe Mathieu-Daudétry: 31*ef83aea0SPhilippe Mathieu-Daudé import cv2 32*ef83aea0SPhilippe Mathieu-Daudéexcept ImportError: 33*ef83aea0SPhilippe Mathieu-Daudé CV2_AVAILABLE = False 34*ef83aea0SPhilippe Mathieu-Daudé 35*ef83aea0SPhilippe Mathieu-Daudé 36*ef83aea0SPhilippe Mathieu-Daudéclass IntegratorMachine(QemuSystemTest): 37*ef83aea0SPhilippe Mathieu-Daudé 38*ef83aea0SPhilippe Mathieu-Daudé timeout = 90 39*ef83aea0SPhilippe Mathieu-Daudé 40*ef83aea0SPhilippe Mathieu-Daudé ASSET_KERNEL = Asset( 41*ef83aea0SPhilippe Mathieu-Daudé ('https://github.com/zayac/qemu-arm/raw/master/' 42*ef83aea0SPhilippe Mathieu-Daudé 'arm-test/kernel/zImage.integrator'), 43*ef83aea0SPhilippe Mathieu-Daudé '26e7c7e8f943de785d95bd3c74d66451604a9b6a7a3d25dceb279e7548fd8e78') 44*ef83aea0SPhilippe Mathieu-Daudé 45*ef83aea0SPhilippe Mathieu-Daudé ASSET_INITRD = Asset( 46*ef83aea0SPhilippe Mathieu-Daudé ('https://github.com/zayac/qemu-arm/raw/master/' 47*ef83aea0SPhilippe Mathieu-Daudé 'arm-test/kernel/arm_root.img'), 48*ef83aea0SPhilippe Mathieu-Daudé 'e187c27fb342ad148c7f33475fbed124933e0b3f4be8c74bc4f3426a4793373a') 49*ef83aea0SPhilippe Mathieu-Daudé 50*ef83aea0SPhilippe Mathieu-Daudé ASSET_TUXLOGO = Asset( 51*ef83aea0SPhilippe Mathieu-Daudé ('https://github.com/torvalds/linux/raw/v2.6.12/' 52*ef83aea0SPhilippe Mathieu-Daudé 'drivers/video/logo/logo_linux_vga16.ppm'), 53*ef83aea0SPhilippe Mathieu-Daudé 'b762f0d91ec018887ad1b334543c2fdf9be9fdfc87672b409211efaa3ea0ef79') 54*ef83aea0SPhilippe Mathieu-Daudé 55*ef83aea0SPhilippe Mathieu-Daudé def boot_integratorcp(self): 56*ef83aea0SPhilippe Mathieu-Daudé kernel_path = self.ASSET_KERNEL.fetch() 57*ef83aea0SPhilippe Mathieu-Daudé initrd_path = self.ASSET_INITRD.fetch() 58*ef83aea0SPhilippe Mathieu-Daudé 59*ef83aea0SPhilippe Mathieu-Daudé self.set_machine('integratorcp') 60*ef83aea0SPhilippe Mathieu-Daudé self.vm.set_console() 61*ef83aea0SPhilippe Mathieu-Daudé self.vm.add_args('-kernel', kernel_path, 62*ef83aea0SPhilippe Mathieu-Daudé '-initrd', initrd_path, 63*ef83aea0SPhilippe Mathieu-Daudé '-append', 'printk.time=0 console=ttyAMA0') 64*ef83aea0SPhilippe Mathieu-Daudé self.vm.launch() 65*ef83aea0SPhilippe Mathieu-Daudé 66*ef83aea0SPhilippe Mathieu-Daudé @skipUnless(os.getenv('QEMU_TEST_ALLOW_UNTRUSTED_CODE'), 'untrusted code') 67*ef83aea0SPhilippe Mathieu-Daudé def test_integratorcp_console(self): 68*ef83aea0SPhilippe Mathieu-Daudé """ 69*ef83aea0SPhilippe Mathieu-Daudé Boots the Linux kernel and checks that the console is operational 70*ef83aea0SPhilippe Mathieu-Daudé """ 71*ef83aea0SPhilippe Mathieu-Daudé self.boot_integratorcp() 72*ef83aea0SPhilippe Mathieu-Daudé wait_for_console_pattern(self, 'Log in as root') 73*ef83aea0SPhilippe Mathieu-Daudé 74*ef83aea0SPhilippe Mathieu-Daudé @skipUnless(NUMPY_AVAILABLE, 'Python NumPy not installed') 75*ef83aea0SPhilippe Mathieu-Daudé @skipUnless(CV2_AVAILABLE, 'Python OpenCV not installed') 76*ef83aea0SPhilippe Mathieu-Daudé @skipUnless(os.getenv('QEMU_TEST_ALLOW_UNTRUSTED_CODE'), 'untrusted code') 77*ef83aea0SPhilippe Mathieu-Daudé def test_framebuffer_tux_logo(self): 78*ef83aea0SPhilippe Mathieu-Daudé """ 79*ef83aea0SPhilippe Mathieu-Daudé Boot Linux and verify the Tux logo is displayed on the framebuffer. 80*ef83aea0SPhilippe Mathieu-Daudé """ 81*ef83aea0SPhilippe Mathieu-Daudé screendump_path = os.path.join(self.workdir, "screendump.pbm") 82*ef83aea0SPhilippe Mathieu-Daudé tuxlogo_path = self.ASSET_TUXLOGO.fetch() 83*ef83aea0SPhilippe Mathieu-Daudé 84*ef83aea0SPhilippe Mathieu-Daudé self.boot_integratorcp() 85*ef83aea0SPhilippe Mathieu-Daudé framebuffer_ready = 'Console: switching to colour frame buffer device' 86*ef83aea0SPhilippe Mathieu-Daudé wait_for_console_pattern(self, framebuffer_ready) 87*ef83aea0SPhilippe Mathieu-Daudé self.vm.cmd('human-monitor-command', command_line='stop') 88*ef83aea0SPhilippe Mathieu-Daudé self.vm.cmd('human-monitor-command', 89*ef83aea0SPhilippe Mathieu-Daudé command_line='screendump %s' % screendump_path) 90*ef83aea0SPhilippe Mathieu-Daudé logger = logging.getLogger('framebuffer') 91*ef83aea0SPhilippe Mathieu-Daudé 92*ef83aea0SPhilippe Mathieu-Daudé cpu_count = 1 93*ef83aea0SPhilippe Mathieu-Daudé match_threshold = 0.92 94*ef83aea0SPhilippe Mathieu-Daudé screendump_bgr = cv2.imread(screendump_path) 95*ef83aea0SPhilippe Mathieu-Daudé screendump_gray = cv2.cvtColor(screendump_bgr, cv2.COLOR_BGR2GRAY) 96*ef83aea0SPhilippe Mathieu-Daudé result = cv2.matchTemplate(screendump_gray, cv2.imread(tuxlogo_path, 0), 97*ef83aea0SPhilippe Mathieu-Daudé cv2.TM_CCOEFF_NORMED) 98*ef83aea0SPhilippe Mathieu-Daudé loc = np.where(result >= match_threshold) 99*ef83aea0SPhilippe Mathieu-Daudé tux_count = 0 100*ef83aea0SPhilippe Mathieu-Daudé for tux_count, pt in enumerate(zip(*loc[::-1]), start=1): 101*ef83aea0SPhilippe Mathieu-Daudé logger.debug('found Tux at position [x, y] = %s', pt) 102*ef83aea0SPhilippe Mathieu-Daudé self.assertGreaterEqual(tux_count, cpu_count) 103*ef83aea0SPhilippe Mathieu-Daudé 104*ef83aea0SPhilippe Mathieu-Daudéif __name__ == '__main__': 105*ef83aea0SPhilippe Mathieu-Daudé QemuSystemTest.main() 106