aboutsummaryrefslogtreecommitdiff
path: root/deprecated/dejagnu/gdb_dejagnu.py
diff options
context:
space:
mode:
Diffstat (limited to 'deprecated/dejagnu/gdb_dejagnu.py')
-rwxr-xr-xdeprecated/dejagnu/gdb_dejagnu.py357
1 files changed, 357 insertions, 0 deletions
diff --git a/deprecated/dejagnu/gdb_dejagnu.py b/deprecated/dejagnu/gdb_dejagnu.py
new file mode 100755
index 00000000..91fa51fd
--- /dev/null
+++ b/deprecated/dejagnu/gdb_dejagnu.py
@@ -0,0 +1,357 @@
+#!/usr/bin/python2
+
+# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""The gdb dejagnu test wrapper."""
+import optparse
+import os
+from os import path
+import re
+import shutil
+import stat
+import sys
+import tempfile
+import time
+
+from cros_utils import command_executer
+from cros_utils import logger
+from cros_utils import misc
+
+from run_dejagnu import TryAcquireMachine
+
+_VALID_TEST_RESULTS = ['FAIL', 'UNRESOLVED', 'XPASS', 'ERROR', 'UNSUPPORTED',
+ 'PASS']
+
+
+def ProcessArguments(argv):
+ """Processing/validating script arguments."""
+ parser = optparse.OptionParser(description=(
+ 'Launches gdb dejagnu test in chroot for chromeos toolchain, compares '
+ 'the test result with a repository baseline and prints out the result.'),
+ usage='run_dejagnu options')
+ parser.add_option('-c',
+ '--chromeos_root',
+ dest='chromeos_root',
+ help='Required. Specify chromeos root')
+ parser.add_option('-m',
+ '--mount',
+ dest='mount',
+ help=('Specify gdb source to mount instead of "auto". '
+ 'Under "auto" mode, which is the default - gdb is '
+ 'checked out and built automatically at default '
+ 'directories. Under "mount" mode '
+ '- the gdb_source is set to "$chromeos_'
+ 'root/chroot/usr/local/toolchain_root/gdb", which is '
+ 'the mount point for this option value.'))
+ parser.add_option('-b',
+ '--board',
+ dest='board',
+ help=('Required. Specify board.'))
+ parser.add_option('-r',
+ '--remote',
+ dest='remote',
+ help=('Required. Specify addresses/names of the board, '
+ 'seperate each address/name using comma(\',\').'))
+ parser.add_option('--cleanup',
+ dest='cleanup',
+ default=None,
+ help=('Optional. Values to this option could be '
+ '\'chroot\' (delete chroot) and '
+ '\'chromeos\' (delete the whole chromeos tree).'))
+
+ options, args = parser.parse_args(argv)
+
+ if not options.chromeos_root:
+ raise SyntaxError('Missing argument for --chromeos_root.')
+ if not options.remote:
+ raise SyntaxError('Missing argument for --remote.')
+ if not options.board:
+ raise SyntaxError('Missing argument for --board.')
+ if options.cleanup == 'mount' and not options.mount:
+ raise SyntaxError('--cleanup=\'mount\' not valid unless --mount is given.')
+ if options.cleanup and not (options.cleanup == 'mount' or
+ options.cleanup == 'chroot' or
+ options.cleanup == 'chromeos'):
+ raise SyntaxError('Invalid option value for --cleanup')
+
+ return options
+
+
+class DejagnuExecuter(object):
+ """The class wrapper for dejagnu test executer."""
+
+ def __init__(self, base_dir, source_dir, chromeos_root, remote, board,
+ cleanup):
+ self._l = logger.GetLogger()
+ self._chromeos_root = chromeos_root
+ self._chromeos_chroot = path.join(chromeos_root, 'chroot')
+
+ self._remote = remote
+ self._board = board
+ ## Compute target from board
+ self._target = misc.GetCtargetFromBoard(board, chromeos_root)
+ if not self._target:
+ raise RuntimeError('Unsupported board "%s"' % board)
+ self._executer = command_executer.GetCommandExecuter()
+ self._base_dir = base_dir
+ self._tmp_abs = None
+ self._cleanup = cleanup
+ self._sshflag = ('-o StrictHostKeyChecking=no ' + '-o CheckHostIP=no ' +
+ '-o UserKnownHostsFile=$(mktemp) ')
+
+ if source_dir:
+ self._source_dir = source_dir
+ self._mount_flag = 'USE="mounted_sources"'
+ self.MountSource()
+ else:
+ self._source_dir = None
+ self._mount_flag = ''
+
+ def SetupTestingDir(self):
+ self._tmp_abs = tempfile.mkdtemp(
+ prefix='dejagnu_',
+ dir=path.join(self._chromeos_chroot, 'tmp'))
+ self._tmp = self._tmp_abs[len(self._chromeos_chroot):]
+ self._tmp_testing_rsa = path.join(self._tmp, 'testing_rsa')
+ self._tmp_testing_rsa_abs = path.join(self._tmp_abs, 'testing_rsa')
+
+ def PrepareTestingRsaKeys(self):
+ if not path.isfile(self._tmp_testing_rsa_abs):
+ shutil.copy(
+ path.join(self._chromeos_root,
+ 'src/scripts/mod_for_test_scripts/ssh_keys/testing_rsa'),
+ self._tmp_testing_rsa_abs)
+ os.chmod(self._tmp_testing_rsa_abs, stat.S_IRUSR)
+
+ def PrepareTestFiles(self):
+ """Prepare site.exp and board exp files."""
+ # Create the boards directory.
+ os.mkdir('%s/boards' % self._tmp_abs)
+
+ # Generate the chromeos.exp file.
+ with open('%s/boards/gdb.exp.in' % self._base_dir, 'r') as template_file:
+ content = template_file.read()
+
+ substitutions = dict({
+ '__boardname__': self._board,
+ '__board_hostname__': self._remote,
+ '__tmp_testing_rsa__': self._tmp_testing_rsa,
+ '__tmp_dir__': self._tmp
+ })
+ for pat, sub in substitutions.items():
+ content = content.replace(pat, sub)
+
+ board_file_name = '%s/boards/%s.exp' % (self._tmp_abs, self._board)
+ with open(board_file_name, 'w') as board_file:
+ board_file.write(content)
+
+ # Generate the site file
+ with open('%s/site.exp' % self._tmp_abs, 'w') as site_file:
+ site_file.write('set target_list "%s"\n' % self._board)
+
+ with open('%s/boards/gdbserver.sh.in' % self._base_dir, 'r') \
+ as template_file:
+ content = template_file.read()
+ substitutions = dict({
+ '__board_hostname__': self._remote,
+ '__tmp_testing_rsa__': self._tmp_testing_rsa,
+ '__tmp_dir__': self._tmp
+ })
+ for pat, sub in substitutions.items():
+ content = content.replace(pat, sub)
+
+ gdbserver_file_name = '%s/boards/gdbserver.sh' % (self._tmp_abs)
+ with open(gdbserver_file_name, 'w') as board_file:
+ board_file.write(content)
+
+ st = os.stat(gdbserver_file_name)
+ os.chmod(gdbserver_file_name, st.st_mode | stat.S_IXGRP | stat.S_IXUSR)
+
+ def PrepareGdb(self):
+ self.PrepareGdbDefault()
+
+ def PrepareGdbDefault(self):
+ ret = self._executer.ChrootRunCommandWOutput(
+ self._chromeos_root, 'equery w cross-%s/gdb' % self._target)[1]
+ ret = path.basename(ret.strip())
+
+ matcher = re.match(r'(.*).ebuild', ret)
+ if matcher:
+ gdb_reversion = matcher.group(1)
+ else:
+ raise RuntimeError('Failed to get gdb reversion.')
+ gdb_version = gdb_reversion.split('-r')[0]
+ gdb_portage_dir = '/var/tmp/portage/cross-%s/%s/work' % (self._target,
+ gdb_reversion)
+ self._gdb_source_dir = path.join(gdb_portage_dir, gdb_version)
+
+ ret = self._executer.ChrootRunCommand(self._chromeos_root, (
+ 'sudo %s ebuild $(equery w cross-%s/gdb) clean compile' % (
+ self._mount_flag, self._target)))
+ if ret:
+ raise RuntimeError('ebuild gdb failed.')
+
+ def PrepareGdbserver(self):
+ self.PrepareGdbserverDefault()
+
+ def PrepareGdbserverDefault(self):
+ cmd = ('setup_board --board {0}; '
+ '{1} emerge-{0} gdb'.format(self._board, self._mount_flag))
+ ret = self._executer.ChrootRunCommand(self._chromeos_root,
+ cmd,
+ print_to_console=True)
+ if ret:
+ raise RuntimeError('ebuild gdbserver failed.')
+
+ cmd = ('scp -i {0} {1} '
+ '/build/{2}/usr/bin/gdbserver root@{3}:/usr/local/bin/'.format(
+ self._tmp_testing_rsa, self._sshflag, self._board, self._remote))
+ ret = self._executer.ChrootRunCommand(self._chromeos_root,
+ cmd,
+ print_to_console=True)
+ if ret:
+ raise RuntimeError('copy gdbserver failed.')
+
+ if self._mount_flag:
+ self.MountSource(unmount=False)
+
+ def Cleanup(self):
+ if not self._cleanup:
+ return
+
+ if self._cleanup == 'chroot' or self._cleanup == 'chromeos':
+ self._l.LogOutput('[Cleanup]: Deleting chroot inside \'{0}\''.format(
+ self._chromeos_root))
+ command = 'cd %s; cros_sdk --delete' % self._chromeos_root
+ rv = self._executer.RunCommand(command)
+ if rv:
+ self._l.LogWarning('Warning - failed to delete chroot.')
+ # Delete .cache - crosbug.com/34956
+ command = 'sudo rm -fr %s' % os.path.join(self._chromeos_root, '.cache')
+ rv = self._executer.RunCommand(command)
+ if rv:
+ self._l.LogWarning('Warning - failed to delete \'.cache\'.')
+
+ if self._cleanup == 'chromeos':
+ self._l.LogOutput('[Cleanup]: Deleting chromeos tree \'{0}\' ...'.format(
+ self._chromeos_root))
+ command = 'rm -fr {0}'.format(self._chromeos_root)
+ rv = self._executer.RunCommand(command)
+ if rv:
+ self._l.LogWarning('Warning - failed to remove chromeos tree.')
+
+ def MakeCheck(self):
+ cmd = ('ssh -i {0} {1} root@{2} "reboot && exit"'
+ .format(self._tmp_testing_rsa, self._sshflag, self._remote))
+ self._executer.ChrootRunCommand(self._chromeos_root, cmd)
+ time.sleep(40)
+
+ cmd = ('ssh -i {0} {1} root@{2} '
+ '"iptables -A INPUT -p tcp --dport 1234 -j ACCEPT"'.format(
+ self._tmp_testing_rsa, self._sshflag, self._remote))
+ self._executer.ChrootRunCommand(self._chromeos_root, cmd)
+
+ cmd = ('cd %s ; '
+ 'DEJAGNU=%s make check' % (path.join(self._gdb_source_dir, 'gdb'),
+ path.join(self._tmp, 'site.exp')))
+ ret = self._executer.ChrootRunCommand(self._chromeos_root, cmd)
+ if ret:
+ raise RuntimeError('Make check failed.')
+
+ # This method ensures necessary mount points before executing chroot comamnd.
+ def MountSource(self, unmount=False):
+ script = os.path.join(self._base_dir, 'build_tc.py')
+ if unmount:
+ mount = '-u'
+ else:
+ mount = '-m'
+ cmd = ('python {0} --chromeos_root={1} '
+ '--gdb_dir={2} --board={3} {4}'.format(script, self._chromeos_root,
+ self._source_dir, self._board,
+ mount))
+ rv = self._executer.RunCommand(cmd)
+ if rv:
+ raise RuntimeError('Mount source failed.')
+
+ def ResultValidate(self):
+ self.PrepareResult()
+ result = []
+ for key, value in self.base_result.items():
+ if 'PASS' not in value:
+ continue
+ if key not in self.test_result:
+ continue
+ test_result = self.test_result[key]
+ if 'PASS' not in test_result:
+ result.append(key)
+ return result
+
+ def PrepareResult(self):
+ test_output = os.path.join(self._gdb_source_dir, 'gdb', 'testsuite',
+ 'gdb.sum')
+ test_output = misc.GetOutsideChrootPath(self._chromeos_root, test_output)
+ base_output = os.path.join(self._base_dir, 'gdb_baseline', self._target)
+
+ self.test_result = self.ParseResult(test_output)
+ self.base_result = self.ParseResult(base_output)
+
+ def ParseResult(self, gdb_sum):
+ result = {}
+ multi_keys = {}
+ with open(gdb_sum) as input_sum:
+ for line in input_sum:
+ line = line.strip()
+ r = line.split(':', 1)
+ if r[0] in _VALID_TEST_RESULTS:
+ key = r[1]
+ if r[1] in result:
+ if r[1] in multi_keys:
+ multi_keys[r[1]] += 1
+ else:
+ multi_keys[r[1]] = 2
+ key = r[1] + '_____{0}_____'.format(multi_keys[r[1]])
+ result[key] = r[0]
+ return result
+
+
+def Main(argv):
+ opts = ProcessArguments(argv)
+ available_machine = TryAcquireMachine(opts.remote)
+ executer = DejagnuExecuter(
+ misc.GetRoot(argv[0])[0], opts.mount, opts.chromeos_root,
+ available_machine._name, opts.board, opts.cleanup)
+ # Return value is a 3- or 4-element tuple
+ # element#1 - exit code
+ # element#2 - stdout
+ # element#3 - stderr
+ # element#4 - exception infor
+ # Some other scripts need these detailed information.
+ ret = (1, '', '')
+ try:
+ executer.SetupTestingDir()
+ executer.PrepareTestingRsaKeys()
+ executer.PrepareTestFiles()
+ executer.PrepareGdb()
+ executer.PrepareGdbserver()
+ executer.MakeCheck()
+ result = executer.ResultValidate()
+ print result
+ if result:
+ ret = (1, result, '')
+ else:
+ ret = (0, '', '')
+
+ except Exception as e:
+ # At least log the exception on console.
+ print e
+ # The #4 element encodes the runtime exception.
+ ret = (1, '', '', 'Exception happened during execution: \n' + str(e))
+ finally:
+ executer.Cleanup()
+ return ret
+
+
+if __name__ == '__main__':
+ retval = Main(sys.argv)[0]
+ sys.exit(retval)