def run_cases_on_image(apk_path, replay_file_list, image_name):
    gui_port = find_free_port()
    appium_port = find_free_port()
    emu_port = find_free_port()
    adb_port = find_free_port()
    print(
        f"[*] port config: gui={gui_port}, appium={appium_port}, emu={emu_port} ,adb={adb_port}"
    )

    print(f"{image_name.split('-')[-1]} [url] http://10.20.38.233:{gui_port}/")

    # adb related config
    adb_connection_str = "localhost:" + str(
        adb_port)  # this is generated at runtime
    remote_addr = "http://localhost:" + str(appium_port) + "/wd/hub"

    # initialize
    client = docker.from_env()
    apkname = Path(apk_path).name
    replace_img_name = image_name.replace("/", "_")

    write_name = f"{apkname}_{replace_img_name}"
    now = datetime.datetime.now()
    # print("[about to init docker]")
    container = docker_init(client=client,
                            image_name=image_name,
                            gui_port=gui_port,
                            appium_port=appium_port,
                            emu_port=emu_port,
                            adb_port=adb_port)
    try:
        adb_connect_install(adb_exe_path=adb_exe_path,
                            adb_connection_str=adb_connection_str,
                            apk_path=apk_path)
    except Exception as e:
        try:
            container.remove(force=True)
            print("{*} container removed.")
        except Exception as e:
            print(case.stem, e)
        return write_name
        log_to_file(f"replay/replay_logs/replay.log_{write_name}",
                    "adbinstall:" + str(e), now, write_name)

    print("{*} remote addr: ", remote_addr)

    for idx, case in enumerate(replay_file_list):
        case = Path(case)
        print("{*} running case: " + str(case) + " with image: " + image_name +
              " apk:" + str(apk_path))
        with open(case, "r", encoding="utf8") as f:
            code = "\n".join(f.readlines())
Ejemplo n.º 2
0
def run_single_apk_task(apk_path):

    print(f"[!] current processing {apk_path}")
    apk_path = str(apk_path)
    container = None
    apk_name = Path(apk_path).stem


    success_finish = True
    try:
        # analyse apk
        # apk_path="/home/luzhirui/jerrylu/mineapk/de.danoeh.antennapod.apk"
        print(f"[!] analyse...")
        aapt_path="/home/luzhirui/jerrylu/android9/android-9/aapt"
        package = "UNKNOWN"
        SDKversion, package, main_activity, minSdk = analyse_apk(apk_path, aapt_path=aapt_path)
        if package == "UNKNOWN":
            return "analyze_apk_failed..."
        print(SDKversion, package, main_activity, minSdk)
        SDKversion = str(SDKversion)

        # docker related config
        APIlevel_androidversion = {
            '21': '5.0.1',
            '22': '5.1.1',
            '23': '6.0',
            '24': '7.0',
            '25': '7.1.1',
            '26': '8.0',
            '27': '8.1',
            '28': '9.0',
            '29': '10.0'
        }
        Android_version = APIlevel_androidversion[SDKversion]
        image_name="budtmo/docker-android-x86-{}".format(Android_version)
        # image_name="budtmo/docker-android-x86-{}".format("9.0")

        gui_port=find_free_port()
        appium_port=find_free_port()
        emu_port=find_free_port()
        adb_port=find_free_port()
        print(f"[*] {apk_name}: port config: gui={gui_port}, appium={appium_port}, emu={emu_port} ,adb={adb_port}")
        with open("port.log", "a") as port_log:
            port_log.write(f"[*] {apk_name}: port config: gui={gui_port}, appium={appium_port}, emu={emu_port} ,adb={adb_port}")
            port_log.write("\n")

        # adb related config
        adb_exe_path="/home/luzhirui/jerrylu/adb/platform-tools/adb"
        adb_connection_str="localhost:" + str(adb_port)  # this is generated at runtime

        # appium desired caps
        desired_caps = {}
        desired_caps['platformName'] = 'Android'
        desired_caps['platformVersion'] = Android_version
        desired_caps['deviceName'] = 'emulator-5554' # This should be fine... They are all called `emulator-5554` internally inside container
        desired_caps['appPackage'] = package
        desired_caps['appActivity'] = main_activity
        desired_caps['eventTimings'] = True
        desired_caps['automationName'] = 'UIAutomator2'
        desired_caps['autoGrantPermissions'] = True

        # test related data containers
        test_num = 0
        # record target APIs triggered
        trigger_target_APIs = set()
        # record activities triggered
        activities = set()
        # record widgets triggered
        widgets = set()
        # record widgets in page_source
        widgets_page_source = set()

        # initialize
        print(f"[!] setting up docker...")
        client = docker.from_env()
        container = docker_init(client=client, image_name=image_name, gui_port=gui_port, appium_port=appium_port, emu_port=emu_port, adb_port=adb_port)
        print(f"[!] starting install apk...")
        adb_connect_install(adb_exe_path=adb_exe_path, adb_connection_str=adb_connection_str,apk_path=apk_path)
        remote_addr = "http://localhost:"+str(appium_port)+"/wd/hub"

        # main test loop
        print(f"[!] entering main test loop...")
        while test_num < 3:
            # try:
            print("\n{} test:\n".format(test_num))
            appium_command = appium_driver_ui(desired_caps, 100, activities, widgets, widgets_page_source, test_num, remote_addr=remote_addr, adb_exe_path=adb_exe_path, apk_name=apk_name, adb_port=adb_port)
            print("\n"+"appium_command:")
            print(appium_command)
            generate_test(appium_command, test_num, trigger_target_APIs, apk_name=apk_name)

            # except Exception as e:
            #     print(e)
            #     print("error: {}".format(test_num) + "test")
            #     exc_type, exc_value, exc_traceback_obj = sys.exc_info()
            #     traceback.print_tb(exc_traceback_obj)
            test_num += 1
            sleep(5)



        # output & save results
        print("triggered activities:")
        print(activities)
        print("triggered executable elements:")
        print(widgets)
        print("triggered target APIs:")
        print(trigger_target_APIs)
        print("all achievable executable elements")
        print(widgets_page_source)
        print("widget coverage:")
        coverage = len(widgets)/len(widgets_page_source)
        print(str(coverage))

        print(f"[!] saving to report...")
        with open(f'report/{apk_name}_report.txt', "w") as f:
            f.write("triggered activities:"+"\n")
            f.write(str(activities)+"\n")
            f.write("triggered executable elements:"+"\n")
            f.write(str(widgets)+"\n")
            f.write("triggered target APIs:"+"\n")
            f.write(str(trigger_target_APIs)+"\n")
            f.write("all achievable executable elements"+"\n")
            f.write(str(widgets_page_source)+"\n")
            f.write("widget coverage:"+"\n")
            f.write(str(coverage))

        print("-----------DONE---------------")
    except FunctionTimedOut as e:
        success_finish = False

        with open(f"generate_logs/{apk_name}.log", "a") as f:
            f.write(str(e))
        print(f"[!] error {e}")
        print("-----------ERROR LAST---------------")
    except Exception as e:

        success_finish = False

        with open(f"generate_logs/{apk_name}.log", "a") as f:
            f.write(str(e))
        print(f"[!] error {e}")
        print("-----------ERROR LAST---------------")
    finally:
        # tear down: remove container
        try:
            if container is not None:
                container.remove(force=True)
        except Exception as e2:
            with open(f"generate_logs/{apk_name}.log", "a") as f:
                f.write(str(e2))
                print(f"[!] error {e2}")

        with open(f"generate_logs/{apk_name}.log", "a") as f:
            f.write("\nsuccess finish:"+str(success_finish))
        print("{*} container removed.")
    
    return apk_path
                                           desired_caps=desired_caps,
                                           write_name=write_name)
     log_to_file(f"replay/replay_logs/replay.log_{write_name}",
                 "SUCCESS!", now, write_name)
 except Exception as e:
     print(case.stem, e)
     exc_type, exc_value, exc_traceback_obj = sys.exc_info()
     traceback.print_tb(exc_traceback_obj)
     log_to_file(f"replay/replay_logs/replay.log_{write_name}",
                 "ERR:" + str(e), now, write_name)
     if "socket hang up" in str(e):
         print("hangup retry1")
         container.remove(force=True)
         container = docker_init(client=client,
                                 image_name=image_name,
                                 gui_port=gui_port,
                                 appium_port=appium_port,
                                 emu_port=emu_port,
                                 adb_port=adb_port)
         adb_connect_install(adb_exe_path=adb_exe_path,
                             adb_connection_str=adb_connection_str,
                             apk_path=apk_path)
         try:
             test_function(remote_addr=remote_addr,
                           desired_caps=desired_caps,
                           write_name=case.stem)
             log_to_file(f"replay/replay_logs/replay.log_{write_name}",
                         "SUCCESS! with retry", now, write_name)
         except Exception as e:
             print(case.stem, e)
             log_to_file(f"replay/replay_logs/replay.log_{write_name}",
                         "ERR(retry):" + str(e), now, write_name)
Ejemplo n.º 4
0
def run_cases_on_image(apk_path, replay_file_list, image_name):
    """
    This runs multiple test case at the same time on a specific image container.
    """

    # find free ports
    gui_port = find_free_port()
    appium_port = find_free_port()
    emu_port = find_free_port()
    adb_port = find_free_port()
    print(
        f"[*] port config: gui={gui_port}, appium={appium_port}, emu={emu_port} ,adb={adb_port}"
    )

    # adb related config
    adb_connection_str = "localhost:" + str(
        adb_port)  # this is generated at runtime
    remote_addr = "http://localhost:" + str(appium_port) + "/wd/hub"

    # initialize
    client = docker.from_env()
    apkname = Path(apk_path).name
    replace_img_name = image_name.replace("/", "_")

    write_name = f"{apkname}_{replace_img_name}"
    now = datetime.datetime.now()

    # prepare container
    # WARNING: THESE ARE NOT LIGHTWEIGHT CONTAINERS! THEY ARE QUITE HEAVY!
    container = docker_init(client=client,
                            image_name=image_name,
                            gui_port=gui_port,
                            appium_port=appium_port,
                            emu_port=emu_port,
                            adb_port=adb_port,
                            name=write_name)
    try:

        # try to install
        # this might lead to timeout, but should not hang up here...
        adb_connect_install(adb_exe_path=adb_exe_path,
                            adb_connection_str=adb_connection_str,
                            apk_path=apk_path)
    except Exception as e:
        # if adb install fail, try to remove the docker???
        print("adb install failed...")
        try:
            log_to_file(f"replay/replay_logs/replay.log_{write_name}",
                        "adbinstall:" + str(e), now, write_name)
            container.remove(force=True)
            container = None
            logging.exception("adb exception happened")
            print("{*} container removed.")
        except FunctionTimedOut:
            logging.exception("adb install timed out")
        except Exception as e:
            logging.exception("adb exception handle failed")
            print(case.stem, e)
        finally:
            return write_name

    # by now, container should be ready, and the apk has been installed
    print("{*} remote addr: ", remote_addr)

    # run all the case one by one
    for idx, case in enumerate(replay_file_list):
        case = Path(case)
        print("{*} running case: " + str(case) + " with image: " + image_name +
              " apk:" + str(apk_path))
        with open(case, "r", encoding="utf8") as f:
            code = "\n".join(f.readlines())