xref: /openbmc/openbmc/poky/meta/lib/oeqa/runexported.py (revision c342db356d4f451821781eb24eb9f3d39d6c0c5e)
1#!/usr/bin/env python3
2#
3# Copyright (C) 2013 Intel Corporation
4#
5# SPDX-License-Identifier: MIT
6#
7
8# This script should be used outside of the build system to run image tests.
9# It needs a json file as input as exported by the build.
10# E.g for an already built image:
11#- export the tests:
12#   TEST_EXPORT_ONLY = "1"
13#   TEST_TARGET  = "simpleremote"
14#   TEST_TARGET_IP = "192.168.7.2"
15#   TEST_SERVER_IP = "192.168.7.1"
16# bitbake core-image-sato -c testimage
17# Setup your target, e.g for qemu: runqemu core-image-sato
18# cd build/tmp/testimage/core-image-sato
19# ./runexported.py testdata.json
20
21import sys
22import os
23import time
24import argparse
25
26try:
27    import simplejson as json
28except ImportError:
29    import json
30
31sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "oeqa")))
32
33from oeqa.oetest import ExportTestContext
34from oeqa.utils.commands import runCmd, updateEnv
35from oeqa.utils.sshcontrol import SSHControl
36
37# this isn't pretty but we need a fake target object
38# for running the tests externally as we don't care
39# about deploy/start we only care about the connection methods (run, copy)
40class FakeTarget(object):
41    def __init__(self, d):
42        self.connection = None
43        self.ip = None
44        self.server_ip = None
45        self.datetime = time.strftime('%Y%m%d%H%M%S',time.gmtime())
46        self.testdir = d.getVar("TEST_LOG_DIR")
47        self.pn = d.getVar("PN")
48
49    def exportStart(self):
50        self.sshlog = os.path.join(self.testdir, "ssh_target_log.%s" % self.datetime)
51        sshloglink = os.path.join(self.testdir, "ssh_target_log")
52        if os.path.lexists(sshloglink):
53            os.remove(sshloglink)
54        os.symlink(self.sshlog, sshloglink)
55        print("SSH log file: %s" %  self.sshlog)
56        self.connection = SSHControl(self.ip, logfile=self.sshlog)
57
58    def run(self, cmd, timeout=None):
59        return self.connection.run(cmd, timeout)
60
61    def copy_to(self, localpath, remotepath):
62        return self.connection.copy_to(localpath, remotepath)
63
64    def copy_from(self, remotepath, localpath):
65        return self.connection.copy_from(remotepath, localpath)
66
67
68class MyDataDict(dict):
69    def getVar(self, key, unused = None):
70        return self.get(key, "")
71
72def main():
73
74    parser = argparse.ArgumentParser()
75    parser.add_argument("-t", "--target-ip", dest="ip", help="The IP address of the target machine. Use this to \
76            overwrite the value determined from TEST_TARGET_IP at build time")
77    parser.add_argument("-s", "--server-ip", dest="server_ip", help="The IP address of this machine. Use this to \
78            overwrite the value determined from TEST_SERVER_IP at build time.")
79    parser.add_argument("-d", "--deploy-dir", dest="deploy_dir", help="Full path to the package feeds, that this \
80            the contents of what used to be DEPLOY_DIR on the build machine. If not specified it will use the value \
81            specified in the json if that directory actually exists or it will error out.")
82    parser.add_argument("-l", "--log-dir", dest="log_dir", help="This sets the path for TEST_LOG_DIR. If not specified \
83            the current dir is used. This is used for usually creating a ssh log file and a scp test file.")
84    parser.add_argument("-a", "--tag", dest="tag", help="Only run test with specified tag.")
85    parser.add_argument("json", help="The json file exported by the build system", default="testdata.json", nargs='?')
86
87    args = parser.parse_args()
88
89    with open(args.json, "r") as f:
90        loaded = json.load(f)
91
92    if args.ip:
93        loaded["target"]["ip"] = args.ip
94    if args.server_ip:
95        loaded["target"]["server_ip"] = args.server_ip
96
97    d = MyDataDict()
98    for key in loaded["d"].keys():
99        d[key] = loaded["d"][key]
100
101    if args.log_dir:
102        d["TEST_LOG_DIR"] = args.log_dir
103    else:
104        d["TEST_LOG_DIR"] = os.path.abspath(os.path.dirname(__file__))
105    if args.deploy_dir:
106        d["DEPLOY_DIR"] = args.deploy_dir
107    else:
108        if not os.path.isdir(d["DEPLOY_DIR"]):
109            print("WARNING: The path to DEPLOY_DIR does not exist: %s" % d["DEPLOY_DIR"])
110
111    parsedArgs = {}
112    parsedArgs["tag"] = args.tag
113
114    extract_sdk(d)
115
116    target = FakeTarget(d)
117    for key in loaded["target"].keys():
118        setattr(target, key, loaded["target"][key])
119
120    target.exportStart()
121    tc = ExportTestContext(d, target, True, parsedArgs)
122    tc.loadTests()
123    tc.runTests()
124
125    return 0
126
127def extract_sdk(d):
128    """
129    Extract SDK if needed
130    """
131
132    export_dir = os.path.dirname(os.path.realpath(__file__))
133    tools_dir = d.getVar("TEST_EXPORT_SDK_DIR")
134    tarball_name = "%s.sh" % d.getVar("TEST_EXPORT_SDK_NAME")
135    tarball_path = os.path.join(export_dir, tools_dir, tarball_name)
136    extract_path = os.path.join(export_dir, "sysroot")
137    if os.path.isfile(tarball_path):
138        print ("Found SDK tarball %s. Extracting..." % tarball_path)
139        result = runCmd("%s -y -d %s" % (tarball_path, extract_path))
140        for f in os.listdir(extract_path):
141            if f.startswith("environment-setup"):
142                print("Setting up SDK environment...")
143                env_file = os.path.join(extract_path, f)
144                updateEnv(env_file)
145
146if __name__ == "__main__":
147    try:
148        ret = main()
149    except Exception:
150        ret = 1
151        import traceback
152        traceback.print_exc()
153    sys.exit(ret)
154