aboutsummaryrefslogtreecommitdiff
path: root/dejagnu
diff options
context:
space:
mode:
authorYunlian Jiang <yunlian@google.com>2013-04-16 10:26:36 -0700
committerChromeBot <chrome-bot@google.com>2013-04-22 16:44:24 -0700
commitf5533e3b5edce07360f6362569f51c726e7ff838 (patch)
tree713061559dec4959d61fec1199f8dca556937f14 /dejagnu
parent6845e5f094d67d45a6908e2cfdfed25476b8e343 (diff)
downloadtoolchain-utils-f5533e3b5edce07360f6362569f51c726e7ff838.tar.gz
Add gdb_dejiagnu test script
This is the basic dejagnu test script. Currently it just generate the board information, compile gdb/gdbserver and run make check. It needs baseline and some other features later. BUG=None TEST=./gdb_dejagnu.py -c /extend/gamma/ -b lumpy -r 172.17.128.241 It finishes the dejagnu run. Change-Id: I81678926eda640bb5637e6e4dc540a7b9801b000 Reviewed-on: https://gerrit-int.chromium.org/35703 Reviewed-by: Han Shen <shenhan@google.com> Commit-Queue: Yunlian Jiang <yunlian@google.com> Tested-by: Yunlian Jiang <yunlian@google.com>
Diffstat (limited to 'dejagnu')
-rw-r--r--dejagnu/boards/gdb.exp.in133
-rw-r--r--dejagnu/boards/gdbserver.sh.in12
-rwxr-xr-xdejagnu/gdb_dejagnu.py314
3 files changed, 459 insertions, 0 deletions
diff --git a/dejagnu/boards/gdb.exp.in b/dejagnu/boards/gdb.exp.in
new file mode 100644
index 00000000..1729d608
--- /dev/null
+++ b/dejagnu/boards/gdb.exp.in
@@ -0,0 +1,133 @@
+# Copyright 2011-2012 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This file is a dejagnu "board file" and is used to run the testsuite
+# natively with gdbserver.
+#
+# To use this file:
+# bash$ touch ${my_dejagnu_dir}/my-dejagnu.exp
+# bash$ export DEJAGNU=${my_dejagnu_dir}/my-dejagnu.exp
+# bash$ mkdir ${my_dejagnu_dir}/boards
+# bash$ cp ${src_dir}/gdb/testsuite/boards/native-gdbserver.exp \
+# ${my_dejagnu_dir}/boards
+# bash$ cd ${build_dir}/gdb
+# bash$ make check RUNTESTFLAGS="--target_board=native-gdbserver"
+
+load_generic_config "gdbserver"
+process_multilib_options ""
+
+# The default compiler for this target.
+set_board_info compiler "[find_gcc]"
+
+set_board_info cflags "-fno-stack-protector"
+set_board_info cxxflags "-fno-stack-protector"
+
+set remote_directory "/tmp"
+set chrome_device_ip __board_hostname__
+
+# This gdbserver can only run a process once per session.
+set_board_info gdb,do_reload_on_run 1
+
+# There's no support for argument-passing (yet).
+set_board_info noargs 1
+
+# Can't do input (or output) in the current gdbserver.
+set_board_info gdb,noinferiorio 1
+
+# gdbserver does not intercept target file operations and perform them
+# on the host.
+set_board_info gdb,nofileio 1
+
+#set_board_info sockethost "localhost:"
+set_board_info use_gdb_stub 1
+
+# We will be using the standard GDB remote protocol.
+set_board_info gdb_protocol "remote"
+
+# Test the copy of gdbserver in the build directory.
+# set_board_info gdb_server_prog "../gdbserver/gdbserver"
+
+# Can't do hardware watchpoints, in general (it depends on gdbserver support for your target arch)
+set_board_info gdb,no_hardware_watchpoints 1
+
+#Can't do record
+set_board_info gdb,use_precord 0
+set_board_info gdb,can_reverse 0
+
+
+set gdb_test_timeout 60
+set_board_info timeout 60
+
+set_board_info ssh,options "-i __tmp_testing_rsa__ -o ControlMaster=auto -o ControlPath=__tmp_dir__/%r@%h:%p -o StrictHostKeyChecking=no"
+
+set_board_info gdb_server_prog "__tmp_dir__/boards/gdbserver.sh "
+set_board_info sockethost "__board_hostname__:"
+set_board_info protocol standard
+set_board_info gdb,socketport "1234"
+
+
+proc ${board}_spawn { board cmd } {
+ global board_info
+
+ set baseboard [lindex [split $board "/"] 0]
+
+ set board_info($baseboard,isremote) 0
+ set result [remote_spawn $board $cmd]
+ set board_info($baseboard,isremote) 1
+
+ return $result
+}
+
+proc ${board}_exec { hostname program args } {
+ global board_info
+ verbose -log "$hostname $program $args"
+ set baseboard [lindex [split $hostname "/"] 0]
+
+ set board_info($baseboard,isremote) 0
+ set result [remote_exec $hostname $program $args]
+ set board_info($baseboard,isremote) 1
+
+ return $result
+}
+
+proc ${board}_download { board host dest } {
+ verbose -log "chrome_download $board $host $dest"
+ global board_info
+ set ssh_options [board_info $board ssh,options]
+
+ global chrome_device_ip remote_directory remote_file
+
+ verbose -log "scp -q $ssh_options $host root@$chrome_device_ip:$remote_directory/$dest"
+ set status [catch "exec scp -q $ssh_options $host root@$chrome_device_ip:$remote_directory/$dest" output]
+
+ if { $status == 0 } {
+ verbose -log "Copied $host to $remote_directory/$dest" 2
+ return "$remote_directory/$dest"
+ } else{
+ verbose -log "Download to $dest failed, $output." 2
+ return ""
+ }
+}
+
+proc ${board}_file { dest op args } {
+ if { $op == "delete" } {
+ return 0
+ }
+ return [eval [list standard_file $dest $op] $args]
+}
+
+proc skip_shlid_tests {} {
+ return 1
+}
diff --git a/dejagnu/boards/gdbserver.sh.in b/dejagnu/boards/gdbserver.sh.in
new file mode 100644
index 00000000..c1c048be
--- /dev/null
+++ b/dejagnu/boards/gdbserver.sh.in
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+REMOTE_SSH_FLAGS="-i __tmp_testing_rsa__ -o StrictHostKeyChecking=no -o CheckHostIP=no -o BatchMode=yes -o ControlMaster=auto -o ControlPath=__tmp_dir__/%r@%h:%p"
+FLAGS_remote=__board_hostname__
+
+gdbserver_cmd="/usr/local/bin/gdbserver $1 $2 $3"
+ssh_cmd="nohup ${gdbserver_cmd} "
+
+echo "Executing: ssh ${RSA_FILE} ${REMOTE_SSH_FLAGS} root@${FLAGS_remote} \"${ssh_cmd}\"" >&2
+
+ssh ${REMOTE_SSH_FLAGS} root@${FLAGS_remote} "${ssh_cmd}"
+
diff --git a/dejagnu/gdb_dejagnu.py b/dejagnu/gdb_dejagnu.py
new file mode 100755
index 00000000..e95f84ac
--- /dev/null
+++ b/dejagnu/gdb_dejagnu.py
@@ -0,0 +1,314 @@
+#! /usr/bin/python
+
+# 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.
+
+import getpass
+import optparse
+import os
+from os import path
+import re
+import shutil
+import stat
+import sys
+import tempfile
+import time
+
+import lock_machine
+import tc_enter_chroot
+
+from utils import command_executer
+from utils import constants
+from utils import logger
+from utils import misc
+
+
+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 Exception('Missing argument for --chromeos_root.')
+ if not options.remote:
+ raise Exception('Missing argument for --remote.')
+ if not options.board:
+ raise Exception('Missing argument for --board.')
+ if options.cleanup == 'mount' and not options.mount:
+ raise Exception('--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 Exception('Invalid option value for --cleanup')
+ if options.cleanup and options.keep_intermediate_files:
+ raise Exception('Only one of --keep and --cleanup could be given.')
+
+ return options
+
+
+class DejagnuExecuter(object):
+ """The class wrapper for dejagnu test executer."""
+
+ def __init__(self, base_dir, source_dir, chromeos_root, remote, board,
+ tools, 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 Exception('Unsupported board "%s"' % board)
+ self._executer = command_executer.GetCommandExecuter()
+ self._base_dir = base_dir
+ self._tmp_abs = None
+ self._tools = tools.split(',')
+ self._cleanup = cleanup
+ self._sshflag = " -o StrictHostKeyChecking=no -o CheckHostIP=no"
+
+ 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.ChrootRunCommand(
+ self._chromeos_root,
+ 'equery w cross-%s/gdb' % self._target, return_output=True)[1]
+ ret = path.basename(ret.strip())
+
+ matcher = re.match(r'(.*).ebuild', ret)
+ if matcher:
+ gdb_reversion = matcher.group(1)
+ else:
+ raise Exception('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 Exception('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 Exception('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 Exception('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 Exception('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))
+
+
+def Main(argv):
+ opts = ProcessArguments(argv)
+ available_machine = opts.remote
+ executer = DejagnuExecuter(misc.GetRoot(argv[0])[0],
+ opts.mount, opts.chromeos_root,
+ available_machine,
+ opts.board, opts.flags,
+ opts.keep_intermediate_files, "",
+ 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()
+ # ret = executer.ValidateFailures()
+ 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:
+ #available_machine.Unlock(exclusive=True)
+ #executer.CleanupIntermediateFiles()
+ #executer.Cleanup()
+ return ret
+
+if __name__ == '__main__':
+ retval = Main(sys.argv)[0]
+ sys.exit(retval)
+D