xref: /llvm-project/llvm/test/tools/llvm-debuginfod/llvm-debuginfod.test (revision 71978fcdc2e190998379c035a5e5489c949f4f97)
1# REQUIRES: curl, httplib, thread_support
2# UNSUPPORTED: system-windows
3
4#int main () {
5#  int x = 1;
6#  return x;
7#}
8#
9#Build as : clang -g main.c -o main-debug.exe
10#Then run : cp main-debug.exe main.exe && strip main.exe
11#resulting buildid: 2c39b7557c50162aaeb5a3148c9f76e6e46012e3
12
13# RUN: rm -rf %t
14# RUN: mkdir %t
15# # Query the debuginfod server for artifacts
16# RUN: DEBUGINFOD_CACHE_PATH=%t %python %s --server-cmd 'llvm-debuginfod -v -c 3 %S/Inputs' \
17# RUN:   --tool-cmd 'llvm-debuginfod-find --dump --executable 2c39b7557c50162aaeb5a3148c9f76e6e46012e3' | \
18# RUN:   diff - %S/Inputs/main.exe
19# RUN: DEBUGINFOD_CACHE_PATH=%t %python %s --server-cmd 'llvm-debuginfod -v -c 3 %S/Inputs' \
20# RUN:   --tool-cmd 'llvm-debuginfod-find --dump --debuginfo 2c39b7557c50162aaeb5a3148c9f76e6e46012e3' | \
21# RUN:   diff - %S/Inputs/main-debug.exe
22# Debuginfod server does not yet support source files
23
24# # The artifacts should still be present in the cache without needing to query
25# # the server.
26# RUN: DEBUGINFOD_CACHE_PATH=%t llvm-debuginfod-find --dump \
27# RUN:   --executable 2c39b7557c50162aaeb5a3148c9f76e6e46012e3 | \
28# RUN:   diff - %S/Inputs/main.exe
29# RUN: DEBUGINFOD_CACHE_PATH=%t llvm-debuginfod-find --dump \
30# RUN:   --debuginfo 2c39b7557c50162aaeb5a3148c9f76e6e46012e3 | \
31# RUN:   diff - %S/Inputs/main-debug.exe
32
33
34
35# This script is used to test the debuginfod client within a host tool against
36# the debuginfod server.
37# It first stands up the debuginfod server and then executes the tool.
38# This way the tool can make debuginfod HTTP requests to the debuginfod server.
39import argparse
40import threading
41import subprocess
42import sys
43import os
44import io
45
46# Starts the server and obtains the port number from the first line of stdout.
47# Waits until the server has completed one full directory scan before returning.
48def start_debuginfod_server(server_args):
49    process = subprocess.Popen(
50        server_args,
51        env=os.environ,
52        stdout=subprocess.PIPE)
53    port = -1
54    # Obtain the port.
55    stdout_reader = io.TextIOWrapper(process.stdout, encoding='ascii')
56    stdout_line = stdout_reader.readline()
57    port = int(stdout_line.split()[-1])
58    # Wait until a directory scan is completed.
59    while True:
60        stdout_line = stdout_reader.readline().strip()
61        print(stdout_line, file=sys.stderr)
62        if stdout_line == 'Updated collection':
63            break
64    return (process, port)
65
66# Starts the server with the specified args (if nonempty), then runs the tool
67# with specified args.
68# Sets the DEBUGINFOD_CACHE_PATH env var to point at the given cache_directory.
69# Sets the DEBUGINFOD_URLS env var to point at the local server.
70def test_tool(server_args, tool_args):
71    server_process = None
72    client_process = None
73    port = None
74    server_process, port = start_debuginfod_server(server_args)
75    try:
76        env = os.environ
77        if port is not None:
78            env['DEBUGINFOD_URLS'] = 'http://localhost:%s' % port
79        client_process = subprocess.Popen(
80            tool_args, env=os.environ)
81        client_code = client_process.wait()
82        if client_code != 0:
83            print('nontrivial client return code %s' % client_code, file=sys.stderr)
84            return 1
85        if server_process is not None:
86            server_process.terminate()
87            server_code = server_process.wait()
88            if server_code != -15:
89                print('nontrivial server return code %s' % server_code, file=sys.stderr)
90                return 1
91
92    finally:
93        if server_process is not None:
94            server_process.terminate()
95        if client_process is not None:
96            client_process.terminate()
97    return 0
98
99def main():
100    parser = argparse.ArgumentParser()
101    parser.add_argument('--server-cmd', default='', help='Command to start the server. If not present, no server is started.', type=str)
102    parser.add_argument('--tool-cmd', required=True, type=str)
103    args = parser.parse_args()
104    result = test_tool(args.server_cmd.split(),
105        args.tool_cmd.split())
106    sys.exit(result)
107
108if __name__ == '__main__':
109    main()
110