Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / test / data / nacl / debug_stub_browser_tests.py
blobc128507ac8964984d78a9d55b773b7f29e238e7e
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 import re
6 import sys
7 import xml.etree.ElementTree
9 import gdb_rsp
12 def AssertRaises(exc_class, func):
13 try:
14 func()
15 except exc_class:
16 pass
17 else:
18 raise AssertionError('Function did not raise %r' % exc_class)
21 def GetTargetArch(connection):
22 """Get the CPU architecture of the NaCl application."""
23 reply = connection.RspRequest('qXfer:features:read:target.xml:0,fff')
24 assert reply[0] == 'l', reply
25 tree = xml.etree.ElementTree.fromstring(reply[1:])
26 arch_tag = tree.find('architecture')
27 assert arch_tag is not None, reply
28 return arch_tag.text.strip()
31 def ReverseBytes(byte_string):
32 """Reverse bytes in the hex string: '09ab' -> 'ab09'. This converts
33 little-endian number in the hex string to its normal string representation.
34 """
35 assert len(byte_string) % 2 == 0, byte_string
36 return ''.join([byte_string[i - 2 : i]
37 for i in xrange(len(byte_string), 0, -2)])
40 def GetProgCtrString(connection, arch):
41 """Get current execution point."""
42 registers = connection.RspRequest('g')
43 # PC register indices can be found in
44 # native_client/src/trusted/debug_stub/abi.cc in AbiInit function.
45 if arch == 'i386':
46 # eip index is 8
47 return ReverseBytes(registers[8 * 8 : 8 * 8 + 8])
48 if arch == 'i386:x86-64':
49 # rip index is 16
50 return ReverseBytes(registers[16 * 16 : 16 * 16 + 8])
51 if arch == 'iwmmxt':
52 # pc index is 15
53 return ReverseBytes(registers[15 * 8 : 15 * 8 + 8])
54 raise AssertionError('Unknown architecture: %s' % arch)
57 def TestContinue(connection):
58 # Once the NaCl test module reports that the test passed, the NaCl <embed>
59 # element is removed from the page. The NaCl module will be killed by the
60 # browser which will appear as EOF (end-of-file) on the debug stub socket.
61 AssertRaises(gdb_rsp.EofOnReplyException,
62 lambda: connection.RspRequest('vCont;c'))
65 def TestBreakpoint(connection):
66 # Breakpoints and single-stepping might interfere with Chrome sandbox. So we
67 # check that they work properly in this test.
68 arch = GetTargetArch(connection)
69 registers = connection.RspRequest('g')
70 pc = GetProgCtrString(connection, arch)
71 # Set breakpoint
72 result = connection.RspRequest('Z0,%s,1' % pc)
73 assert result == 'OK', result
74 # Check that we stopped at breakpoint
75 result = connection.RspRequest('vCont;c')
76 stop_reply = re.compile(r'T05thread:(\d+);')
77 assert stop_reply.match(result), result
78 thread = stop_reply.match(result).group(1)
79 # Check that registers haven't changed
80 result = connection.RspRequest('g')
81 assert result == registers, (result, registers)
82 # Remove breakpoint
83 result = connection.RspRequest('z0,%s,1' % pc)
84 assert result == 'OK', result
85 # Check single stepping
86 result = connection.RspRequest('vCont;s:%s' % thread)
87 assert result == 'T05thread:%s;' % thread, result
88 assert pc != GetProgCtrString(connection, arch)
89 # Check that we terminate normally
90 AssertRaises(gdb_rsp.EofOnReplyException,
91 lambda: connection.RspRequest('vCont;c'))
94 def Main(args):
95 port = int(args[0])
96 name = args[1]
97 connection = gdb_rsp.GdbRspConnection(('localhost', port))
98 if name == 'continue':
99 TestContinue(connection)
100 elif name == 'breakpoint':
101 TestBreakpoint(connection)
102 else:
103 raise AssertionError('Unknown test name: %r' % name)
106 if __name__ == '__main__':
107 Main(sys.argv[1:])