<commit_before>"""
Submits the apks to BrowserStack to run the instrumentation tests.
"""

import os
import shlex
import subprocess
from subprocess import PIPE
import sys
import json
import time

def appendData(command, dataUrl):
    var = "file=@{}".format(dataUrl)
    return command + " " + json.dumps(var)

def buildTestCommand(appToken, testToken, classes=None):
    test = {}
    if "BROWSERSTACK_DEVICES" in os.environ:
        list = os.environ["BROWSERSTACK_DEVICES"]
        devices = [x.strip() for x in list.split(',')]
    else:
        devices = ["LG G5-6.0", "Google Nexus 5-4.4"]
    test["devices"] = devices
    test["project"] = "CommCare"
    test["app"] = appToken
    test["deviceLogs"] = True
    test["testSuite"] = testToken
    test["networkLogs"] = True
    test["shards"] = {
        "numberOfShards": 5
    }
    test["annotation"] = ["org.commcare.annotations.BrowserstackTests"]

    if classes:
        test["class"] = classes

    return json.dumps(json.dumps(test))

def isSuccessfulBuild(buildId):
    resultCommand = 'curl -u "{}:{}" -X GET "https://api-cloud.browserstack.com/app-automate/espresso/v2/builds/{}"'.format(userName, password, buildId)
    result = subprocess.Popen(shlex.split(resultCommand), stdout=PIPE, stderr=None, shell=False)
    status = json.loads(result.communicate()[0])["status"]

    while status == "running":
        print("Waiting for tests on browserstack to complete")
        time.sleep(120)
        result = subprocess.Popen(shlex.split(resultCommand), stdout=PIPE, stderr=None, shell=False)
        status = json.loads(result.communicate()[0])["status"]

    return status


def testResult(buildId):
    status = isSuccessfulBuild(buildId)

    # if test succeeded then we can simply return from here.
    if (status == "passed"):
        return

    # Otherwise run the failing test one more time.

    # Get the sessionID from test result
    resultCommand = 'curl -u "{}:{}" -X GET "https://api-cloud.browserstack.com/app-automate/espresso/v2/builds/{}"'.format(userName, password, buildId)
    result = subprocess.Popen(shlex.split(resultCommand), stdout=PIPE, stderr=None, shell=False)
    sessionId = json.loads(result.communicate()[0])["devices"][0]["sessions"][0]["id"]

    # Gather the sessionDetails
    testDetailsCommand = 'curl -u "{}:{}" -X GET "https://api-cloud.browserstack.com/app-automate/espresso/v2/builds/{}/sessions/{}"'.format(userName, password, buildId, sessionId)
    testDetailsResult = subprocess.Popen(shlex.split(testDetailsCommand), stdout=PIPE, stderr=None, shell=False)
    testcases = json.loads(testDetailsResult.communicate()[0])["testcases"]["data"]

    # Create an array of failing classes.
    classes = []
    for testcase in testcases:
        methods = testcase["testcases"]
        for method in methods:
            if (method["status"] != "passed"):
                classes.append("org.commcare.androidTests." + testcase["class"])
                break

    # Now that we know all the test-classes that are failing, we can re-run those.
    print("Failing test classes :: ", classes)

    runConfig = buildTestCommand(appToken, testToken, classes)
    runCmd = 'curl -X POST "{}" -d \ {} -H "Content-Type: application/json" -u "{}:{}"'.format(espressoUrl, runConfig, userName, password)
    output = subprocess.Popen(shlex.split(runCmd), stdout=PIPE, stderr=None, shell=False).communicate()
    buildId = json.loads(output[0])["build_id"]

    status = isSuccessfulBuild(buildId)

    if (status != "passed"):
        print("Instrumentation Tests Failed. Visit browserstack dashboard for more details.")
        print("https://app-automate.browserstack.com/dashboard/v2/builds/{}".format(buildId))
        sys.exit(-1)


if __name__ == "__main__":

    if "BROWSERSTACK_USERNAME" in os.environ:
        userName = os.environ["BROWSERSTACK_USERNAME"]

    if "BROWSERSTACK_PASSWORD" in os.environ:
        password = os.environ["BROWSERSTACK_PASSWORD"]

    releaseApp = os.environ["RELEASE_APP_LOCATION"]
    testApk = os.environ["TEST_APP_LOCATION"]<commit_msg>Modify script to collect failing tests from all sessions of sharded build<commit_after>"""
Submits the apks to BrowserStack to run the instrumentation tests.
"""

import os
import shlex
import subprocess
from subprocess import PIPE
import sys
import json
import time

def appendData(command, dataUrl):
    var = "file=@{}".format(dataUrl)
    return command + " " + json.dumps(var)

def buildTestCommand(appToken, testToken, classes=None):
    test = {}
    if "BROWSERSTACK_DEVICES" in os.environ:
        list = os.environ["BROWSERSTACK_DEVICES"]
        devices = [x.strip() for x in list.split(',')]
    else:
        devices = ["LG G5-6.0", "Google Nexus 5-4.4"]
    test["devices"] = devices
    test["project"] = "CommCare"
    test["app"] = appToken
    test["deviceLogs"] = True
    test["testSuite"] = testToken
    test["networkLogs"] = True
    test["shards"] = {
        "numberOfShards": 5
    }
    test["annotation"] = ["org.commcare.annotations.BrowserstackTests"]

    if classes:
        test["class"] = classes

    return json.dumps(json.dumps(test))

def isSuccessfulBuild(buildId):
    resultCommand = 'curl -u "{}:{}" -X GET "https://api-cloud.browserstack.com/app-automate/espresso/v2/builds/{}"'.format(userName, password, buildId)
    result = subprocess.Popen(shlex.split(resultCommand), stdout=PIPE, stderr=None, shell=False)
    status = json.loads(result.communicate()[0])["status"]

    while status == "running":
        print("Waiting for tests on browserstack to complete")
        time.sleep(120)
        result = subprocess.Popen(shlex.split(resultCommand), stdout=PIPE, stderr=None, shell=False)
        status = json.loads(result.communicate()[0])["status"]

    return status


def testResult(buildId):
    status = isSuccessfulBuild(buildId)

    # if test succeeded then we can simply return from here.
    if (status == "passed"):
        return

    # Otherwise run the failing test one more time.

    # Get the sessionID from test result
    resultCommand = 'curl -u "{}:{}" -X GET "https://api-cloud.browserstack.com/app-automate/espresso/v2/builds/{}"'.format(userName, password, buildId)
    result = subprocess.Popen(shlex.split(resultCommand), stdout=PIPE, stderr=None, shell=False)
    sessions = json.loads(result.communicate()[0])["devices"][0]["sessions"]

    # Loop over all the sessions and Create an array of failing classes.

    classes = []
    for session in sessions:
        if (session["status"] == "passed"):
            continue

        sessionId = session["id"]

        # Gather the sessionDetails
        testDetailsCommand = 'curl -u "{}:{}" -X GET "https://api-cloud.browserstack.com/app-automate/espresso/v2/builds/{}/sessions/{}"'.format(userName, password, buildId, sessionId)
        testDetailsResult = subprocess.Popen(shlex.split(testDetailsCommand), stdout=PIPE, stderr=None, shell=False)
        testcases = json.loads(testDetailsResult.communicate()[0])["testcases"]["data"]

        # Collect the failed classes
        for testcase in testcases:
            methods = testcase["testcases"]
            for method in methods:
                if (method["status"] != "passed"):
                    failedClassName = "org.commcare.androidTests." + testcase["class"]
                    if (failedClassName not in classes):
                        classes.append(failedClassName)
                    break

    # Now that we know all the test-classes that are failing, we can re-run those.
    print("Failing test classes :: ", classes)

    runConfig = buildTestCommand(appToken, testToken, classes)
    runCmd = 'curl -X POST "{}" -d \ {} -H "Content-Type: application/json" -u "{}:{}"'.format(espressoUrl, runConfig, userName, password)
    output = subprocess.Popen(shlex.split(runCmd), stdout=PIPE, stderr=None, shell=False).communicate()
    buildId = json.loads(output[0])["build_id"]

    status = isSuccessfulBuild(buildId)

    if (status != "passed"):
        print("Instrumentation Tests Failed. Visit browserstack dashboard for more details.")
        print("https://app-automate.browserstack.com/dashboard/v2/builds/{}".format(buildId))
        sys.exit(-1)


if __name__ == "__main__":

    if "BROWSERSTACK_USERNAME" in os.environ:
        userName = os.environ["BROWSERSTACK_USERNAME"]

    if "BROWSERSTACK_PASSWORD" in os.environ:
        password = os.environ["BROWSERSTACK_PASSWORD"]

    releaseApp = os.environ["RELEASE_APP_LOCATION"]
    testApk = os.environ["TEST_APP_LOCATION"]
{'fraction_non_alphanumeric': 0.13868783562923184, 'fraction_numerical': 0.005019845902404857, 'mean_word_length': 3.508947368421053, 'pattern_counts': {'":': 6, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 8, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '886443', 'n_tokens_mistral': 2728, 'n_tokens_neox': 2649, 'n_words': 607}