/* checkTag() also tries to lookup the socket address in the kernel and
 * return it when *addr  == NULL.
 * This allows for better look ups when another process is also setting the same
 * tag + uid. But it is not fool proof.
 * Without the kernel reporting more info on who setup the socket tag, it is
 * not easily verifiable from user-space.
 * Returns: true if tag found.
 */
bool SockInfo::checkTag(uint64_t acct_tag, uid_t uid) {
    int ctrl_fd;
    ctrl_fd = openCtrl();
    char ctrl_data[1024];
    ssize_t read_size;
    char *buff;
    char *pos;
    int res;
    char *match_template;
    uint64_t k_tag;
    uint32_t k_uid;
    uint64_t full_tag;
    long dummy_count;
    pid_t dummy_pid;

    read_size = read(ctrl_fd, ctrl_data, sizeof(ctrl_data));
    if (read_size < 0) {
       testPrintE("Unable to read active tags from ctrl %d/%s",
                  errno, strerror(errno));
    }
    ctrl_data[read_size] = '\0';
    testPrintI("<ctrl_raw_data>\n%s</ctrl_raw_data>", ctrl_data);

    if (addr) {
        assert(sizeof(void*) == sizeof(long int));  // Why does %p use 0x? grrr. %lx.
        asprintf(&match_template, "sock=%" PRIxPTR " %s", (uintptr_t)addr, "tag=0x%" PRIx64" (uid=%u)");
    }
    else {
        /* Allocate for symmetry */
        asprintf(&match_template, "%s", " tag=0x%" PRIx64 " (uid=%u)");
    }

    full_tag = acct_tag | uid;

    asprintf(&buff, match_template, full_tag | uid, uid);
    testPrintI("looking for '%s'", buff);
    pos = strstr(ctrl_data, buff);

    if (pos && !addr) {
        assert(sizeof(void*) == sizeof(long int));  // Why does %p use 0x? grrr. %lx.
        res = sscanf(pos - strlen("sock=1234abcd"),
                     "sock=%" SCNxPTR " tag=0x%" SCNx64 " (uid=%" SCNu32 ") pid=%u f_count=%lu",
                     (uintptr_t *)&addr, &k_tag, &k_uid, &dummy_pid, &dummy_count );
        if (!(res == 5 && k_tag == full_tag && k_uid == uid)) {
            testPrintE("Unable to read sock addr res=%d", res);
           addr = 0;
        }
        else {
            testPrintI("Got sock_addr %lx", addr);
        }
    }
    free(buff);
    free(match_template);
    close(ctrl_fd);
    return pos != NULL;
}
/*
 * Initialize
 *
 * Perform testcase initialization, which includes:
 *
 *   1. Determine which CPUs are available for use
 *
 *   2. Determine total number of available CPUs
 *
 *   3. Stop framework
 *
 *   4. Determine whether WiFi driver is loaded and if so
 *      stop wpa_supplicant and unload WiFi driver.
 */
void
init(void)
{
    int rv;
    unsigned int n1;
    char cmd[MAXCMD];

    // Use whichever CPUs are available at start of test
    rv = sched_getaffinity(0, sizeof(availCPU), &availCPU);
    if (rv != 0) {
        testPrintE("init sched_getaffinity failed, rv: %i errno: %i",
            rv, errno);
        exit(40);
    }

    // How many CPUs are available
    numAvailCPU = 0;
    for (n1 = 0; n1 < CPU_SETSIZE; n1++) {
        if (CPU_ISSET(n1, &availCPU)) { numAvailCPU++; }
    }
    testPrintI("numAvailCPU: %u", numAvailCPU);

    // Stop framework
    rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STOP_FRAMEWORK);
    if (rv >= (signed) sizeof(cmd) - 1) {
        testPrintE("Command too long for: %s\n", CMD_STOP_FRAMEWORK);
        exit(41);
    }
    testExecCmd(cmd);

    // Is WiFi driver loaded?
    // If so stop the wpa_supplicant and unload the driver.
    driverLoadedAtStart = is_wifi_driver_loaded();
    testPrintI("driverLoadedAtStart: %u", driverLoadedAtStart);
    if (driverLoadedAtStart) {
        // Stop wpa_supplicant
        // Might already be stopped, in which case request should
        // return immediately with success.
        if ((rv = wifi_stop_supplicant(false)) != 0) {
            testPrintE("init stop supplicant failed, rv: %i", rv);
            exit(42);
        }
        testPrintI("Stopped wpa_supplicant");

        if ((rv = wifi_unload_driver()) != 0) {
            testPrintE("init unload driver failed, rv: %i", rv);
            exit(43);
        }
        testPrintI("WiFi driver unloaded");
    }

}
TEST_F(SocketTaggingTest, TagAnotherSocket) {
    testPrintI("Tag two sockets");
    EXPECT_GE(doCtrlCommand("t %d %" PRIu64, sock0.fd, max_uint_tag), 0);
    EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock1.fd, valid_tag1, fake_uid2), 0);
    EXPECT_TRUE(sock1.checkTag(valid_tag1, fake_uid2)) << "Tag not found.";
    testPrintI("Untag socket0 of them only.");
    EXPECT_GE(doCtrlCommand("u %d", sock0.fd), 0);
    EXPECT_FALSE(sock0.checkTag(max_uint_tag, fake_uid)) << "Tag should not be there";
    EXPECT_TRUE(sock1.checkTag(valid_tag1, fake_uid2)) << "Tag not found";
    testPrintI("Now untag socket1 as well.");
    EXPECT_GE(doCtrlCommand("u %d", sock1.fd), 0);
    EXPECT_FALSE(sock1.checkTag(valid_tag1, fake_uid2)) << "Tag should not be there";
}
TEST(pcmtest, CheckTimer) {
    int ver = 0;
    int fd = open("/dev/snd/timer", O_RDWR | O_NONBLOCK);
    ASSERT_GE(fd, 0);
    int ret = ioctl(fd, SNDRV_TIMER_IOCTL_PVERSION, &ver);
    EXPECT_EQ(0, ret);
    testPrintI(" Timer Version = 0x%x", ver);
    close(fd);
}
/* checkTag() also tries to lookup the socket address in the kernel and
 * return it when *addr  == NULL.
 * This allows for better look ups when another process is also setting the same
 * tag + uid. But it is not fool proof.
 * Without the kernel reporting more info on who setup the socket tag, it is
 * not easily verifiable from user-space.
 * Returns: true if tag found.
 */
bool SockInfo::checkTag(uint64_t acct_tag, uid_t uid) {
    int res;
    uint64_t k_tag;
    uint32_t k_uid;
    long dummy_count;
    pid_t dummy_pid;

    std::ifstream fctrl("/proc/net/xt_qtaguid/ctrl", std::fstream::in);
    if(!fctrl.is_open()) {
        testPrintI("qtaguid ctrl open failed!");
    }

    uint64_t full_tag = acct_tag | uid;
    std::string buff = android::base::StringPrintf(" tag=0x%" PRIx64 " (uid=%u)", full_tag, uid);
    if (addr) {
          buff = android::base::StringPrintf("sock=%" PRIxPTR, (uintptr_t)addr) + buff;
    }

    testPrintI("looking for '%s'", buff.c_str());
    std::string ctrl_data;
    std::size_t pos = std::string::npos;
    while(std::getline(fctrl, ctrl_data)) {
        testPrintI("<ctrl_raw_data> : %s", ctrl_data.c_str());
        pos = ctrl_data.find(buff);
        if (pos != std::string::npos) {
            if(!addr) {
                testPrintI("matched data : %s", ctrl_data.c_str());
                assert(sizeof(void*) == sizeof(long int));
                res = sscanf(ctrl_data.c_str(),
                            "sock=%" SCNxPTR " tag=0x%" SCNx64 " (uid=%" SCNu32 ") pid=%u f_count=%lu",
                            (uintptr_t *)&addr, &k_tag, &k_uid, &dummy_pid, &dummy_count );
                if (!(res == 5 && k_tag == full_tag && k_uid == uid)) {
                    testPrintE("Unable to read sock addr res=%d", res);
                    addr = 0;
                } else {
                    testPrintI("Got sock_addr %lx", addr);
                }
            }
            break;
        }
    }
    return pos != std::string::npos;
}
int getSndDev(unsigned int pcmdevs)
{
    DIR *d;
    struct dirent *de;
    unsigned int prevcard = -1;

    d = opendir(kSoundDir);
    if (d == 0)
        return -ENXIO;
    pcmnodes = (pcm_node_t *)malloc(pcmdevs * sizeof(pcm_node_t));
    if (!pcmnodes)
        return -ENOMEM;
    pcms = 0;
    while ((de = readdir(d)) != NULL) {
        if (de->d_name[0] == '.')
            continue;
        /* printf("%s\n", de->d_name); */
        if (strstr(de->d_name, PCM_PREFIX)) {
            char flags;

            EXPECT_LE(pcms, pcmdevs) << "Too many PCMs";
            if (pcms >= pcmdevs)
                continue;
            sscanf(de->d_name, PCM_PREFIX "C%uD%u", &(pcmnodes[pcms].card),
                   &(pcmnodes[pcms].device));
            flags = de->d_name[strlen(de->d_name)-1];
            if (flags == 'c') {
                pcmnodes[pcms].flags = PCM_IN;
            } else if(flags == 'p') {
                pcmnodes[pcms].flags = PCM_OUT;
            } else {
                pcmnodes[pcms].flags = -1;
                testPrintI("Unknown PCM type = %c", flags);
            }
            if (prevcard != pcmnodes[pcms].card)
                cards++;
            prevcard = pcmnodes[pcms].card;
            pcms++;
            continue;
        }
        if (strstr(de->d_name, MIXER_PREFIX)) {
            unsigned int mixer = -1;
            sscanf(de->d_name, MIXER_PREFIX "C%u", &mixer);
            mixers++;
            continue;
        }
        if (strstr(de->d_name, TIMER_PREFIX)) {
            timers++;
            continue;
        }
    }
    closedir(d);
    return 0;
}
    virtual void SetUp() {
        ctrl_fd = -1;
        dev_fd = -1;
        my_uid = getuid();
        my_pid = getpid();
        srand48(my_pid * my_uid);
        // Adjust fake UIDs and tags so that multiple instances can run in parallel.
        fake_uid = testRand();
        fake_uid2 = testRand();
        valid_tag1 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
        valid_tag2 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
        valid_tag2 &= 0xffffff00ffffffffllu;  // Leave some room to make counts visible.
        testPrintI("* start: pid=%lu uid=%lu uid1=0x%lx/%lu uid2=0x%lx/%lu"
                   " tag1=0x%" PRIx64 "/%" PRIu64 " tag2=0x%" PRIx64 "/% " PRIu64,
                   (unsigned long)my_pid, (unsigned long)my_uid,
                   (unsigned long)fake_uid, (unsigned long)fake_uid,
                   (unsigned long)fake_uid2, (unsigned long)fake_uid2,
                   valid_tag1, valid_tag1, valid_tag2, valid_tag2);
        max_uint_tag = 0xffffffff00000000llu;
        max_uint_tag = 1llu << 63 | (((uint64_t)my_pid << 48) ^ max_uint_tag);

        testPrintI("kernel has qtaguid");
        ctrl_fd = openCtrl();
        ASSERT_GE(ctrl_fd, 0) << "qtaguid ctrl open failed";
        close(ctrl_fd);
        dev_fd = open("/dev/xt_qtaguid", O_RDONLY);
        EXPECT_GE(dev_fd, 0) << "qtaguid dev open failed";

        // We want to clean up any previous faulty test runs.
        testPrintI("delete command does not fail");
        EXPECT_GE(doCtrlCommand("d 0 %u", fake_uid), 0) << "Failed to delete fake_uid";
        EXPECT_GE(doCtrlCommand("d 0 %u", fake_uid2), 0) << "Failed to delete fake_uid2";
        EXPECT_GE(doCtrlCommand("d 0 %u", my_uid), 0) << "Failed to delete my_uid";

        testPrintI("setup sock0 and addr via tag");
        ASSERT_FALSE(sock0.setup(valid_tag1))  << "socket0 setup failed";
        testPrintI("setup sock1 and addr via tag");
        ASSERT_FALSE(sock1.setup(valid_tag1))  << "socket1 setup failed";
    }
TEST_F(SocketTaggingTest, TagData) {
    max_uint_tag = 0xffffffff00000000llu;
    char *max_tags_str;

    testPrintI("setup tag limit");
    asprintf(&max_tags_str, "%d", max_tags);
    ASSERT_GE(writeModuleParam("max_sock_tags", max_tags_str), 0) << "Failed to setup tag limit";

    testPrintI("tag quota reach limit");
    for (int cnt = 0; cnt < max_tags; cnt++ ) {
        uint64_t tag = valid_tag2 + ((uint64_t)cnt << 32);
        EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, tag , fake_uid2), 0)
            << "Tagging within limit failed";
        EXPECT_TRUE(sock0.checkTag(tag, fake_uid2))<<  "Unexpected results: tag not found";
    }

    testPrintI("tag quota go over limit");
    uint64_t new_tag = valid_tag2 + ((uint64_t)max_tags << 32);
    EXPECT_LT(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, new_tag, fake_uid2), 0);
    EXPECT_TRUE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags - 1) << 32),
                               fake_uid2)) << "Unexpected results: tag not found";

    testPrintI("valid untag");
    EXPECT_GE(doCtrlCommand("u %d", sock0.fd), 0);
    EXPECT_FALSE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags - 1) << 32), fake_uid2))
        << "Untagged tag should not be there";

    testPrintI("tag after untag should not free up max tags");
    uint64_t new_tag2 = valid_tag2 + ((uint64_t)max_tags << 32);
    EXPECT_LT(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, new_tag2 , fake_uid2), 0);
    EXPECT_FALSE(sock0.checkTag(valid_tag2 + ((uint64_t)max_tags << 32), fake_uid2))
        << "Tag should not be there";

    testPrintI("delete one tag");
    uint64_t new_tag3 = valid_tag2 + (((uint64_t)max_tags / 2) << 32);
    EXPECT_GE(doCtrlCommand("d %" PRIu64 " %u", new_tag3, fake_uid2), 0);

    testPrintI("2 tags after 1 delete pass/fail");
    uint64_t new_tag4;
    new_tag4 = valid_tag2 + (((uint64_t)max_tags + 1 ) << 32);
    EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, new_tag4 , fake_uid2), 0);
    EXPECT_TRUE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags + 1) << 32), fake_uid2))
        << "Tag not found";
    new_tag4 = valid_tag2 + (((uint64_t)max_tags + 2 ) << 32);
    EXPECT_LT(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, new_tag4 , fake_uid2), 0);
    EXPECT_FALSE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags + 2) << 32), fake_uid2))
        << "Tag should not be there";

    /* TODO(jpa): test tagging two different sockets with same tags and
     * check refcounts  the tag_node should be +2
     */
}
int doCtrlCommand(const char *fmt, ...) {
    char *buff;
    int ctrl;
    int res;
    va_list argp;

    va_start(argp, fmt);
    ctrl = openCtrl();
    vasprintf(&buff, fmt, argp);
    errno = 0;
    res = write(ctrl, buff, strlen(buff));
    testPrintI("cmd: '%s' res=%d %d/%s", buff, res, errno, strerror(errno));
    close(ctrl);
    free(buff);
    va_end(argp);
    return res;
}
/*
 * Random Delay
 *
 * Delays for a random amount of time within the range given
 * by the file scope variables delayMin and delayMax.  The
 * selected amount of delay can come from any part of the
 * range, with a bias towards values closer to delayMin.
 * The amount of bias is determined by the setting of DELAY_EXP.
 * The setting of DELAY_EXP should always be > 1.0, with higher
 * values causing a more significant bias toward the value
 * of delayMin.
 */
void randDelay(void)
{
    const unsigned long nanosecspersec = 1000000000;
    float            fract, biasedFract, amt;
    struct timeval   startTime, endTime;

    // Obtain start time
    gettimeofday(&startTime, NULL);

    // Determine random amount to sleep.
    // Values closer to delayMin are prefered by an amount
    // determined by the value of DELAY_EXP.
    fract = testRandFract();
    biasedFract = pow(DELAY_EXP, fract) / pow(DELAY_EXP, 1.0);
    amt = delayMin + ((delayMax - delayMin) * biasedFract);

    // Delay
    testDelay(amt);

    // Obtain end time and display delta
    gettimeofday(&endTime, NULL);
    testPrintI("delay: %.2f",
        (float) (tv2double(&endTime) - tv2double(&startTime)));
}
/*
 * Main
 *
 * Performs the following high-level sequence of operations:
 *
 *   1. Command-line parsing
 *
 *   2. Initialization
 *
 *   3. Execute passes that repeatedly perform the WiFi load, scan,
 *      associate, unload sequence.
 *
 *   4. Restore state of WiFi driver to state it was at the
 *      start of the test.
 *
 *   5. Restart framework
 */
int
main(int argc, char *argv[])
{
    FILE *fp;
    int rv, opt;
    int cpu;
    char *chptr;
    unsigned int pass;
    char cmd[MAXCMD];
    float duration = DEFAULT_DURATION;
    unsigned int startPass = DEFAULT_START_PASS, endPass = DEFAULT_END_PASS;
    struct timeval startTime, currentTime, delta;

    testSetLogCatTag(LOG_TAG);

    // Parse command line arguments
    while ((opt = getopt(argc, argv, "d:D:s:e:p:t:?")) != -1) {
        switch (opt) {
        case 'd': // Minimum Delay
            delayMin = strtod(optarg, &chptr);
            if ((*chptr != '\0') || (delayMin < 0.0)) {
                testPrintE("Invalid command-line specified minimum delay "
                    "of: %s", optarg);
                exit(1);
            }
            break;

        case 'D': // Maximum Delay
            delayMax = strtod(optarg, &chptr);
            if ((*chptr != '\0') || (delayMax < 0.0)) {
                testPrintE("Invalid command-line specified maximum delay "
                    "of: %s", optarg);
                exit(2);
            }
            break;

        case 't': // Duration
            duration = strtod(optarg, &chptr);
            if ((*chptr != '\0') || (duration < 0.0)) {
                testPrintE("Invalid command-line specified duration of: %s",
                    optarg);
                exit(3);
            }
            break;

        case 's': // Starting Pass
            if (sFlag || pFlag) {
                testPrintE("Invalid combination of command-line options,");
                if (sFlag) {
                    testPrintE("  -s flag specified multiple times.");
                } else {
                    testPrintE("  -s and -p flags are mutually exclusive.");
                }
                exit(10);
            }
            sFlag = true;
            startPass = strtoul(optarg, &chptr, 10);
            if (*chptr != '\0') {
                testPrintE("Invalid command-line specified starting pass "
                    "of: %s", optarg);
                exit(4);
            }
            break;

        case 'e': // Ending Pass
            if (eFlag || pFlag) {
                testPrintE("Invalid combination of command-line options,");
                if (sFlag) {
                    testPrintE("  -e flag specified multiple times.");
                } else {
                    testPrintE("  -e and -p flags are mutually exclusive.");
                }
                exit(11);
            }
            eFlag = true;
            endPass = strtoul(optarg, &chptr, 10);
            if (*chptr != '\0') {
                testPrintE("Invalid command-line specified ending pass "
                    "of: %s", optarg);
                exit(5);
            }
            break;

        case 'p': // Single Specific Pass
            if (pFlag || sFlag || eFlag) {
                testPrintE("Invalid combination of command-line options,");
                if (pFlag) {
                    testPrintE("  -p flag specified multiple times.");
                } else {
                    testPrintE("  -p and -%c flags are mutually exclusive.",
                        (sFlag) ? 's' : 'e');
                }
                exit(12);
            }
            pFlag = true;
            endPass = startPass = strtoul(optarg, &chptr, 10);
            if (*chptr != '\0') {
                testPrintE("Invalid command-line specified pass "
                    "of: %s", optarg);
                exit(13);
            }
            break;

        case '?':
        default:
            testPrintE("  %s [options]", basename(argv[0]));
            testPrintE("    options:");
            testPrintE("      -s Starting pass");
            testPrintE("      -e Ending pass");
            testPrintE("      -p Specific single pass");
            testPrintE("      -t Duration");
            testPrintE("      -d Delay min");
            testPrintE("      -D Delay max");
            exit(((optopt == 0) || (optopt == '?')) ? 0 : 6);
        }
    }
    if (delayMax < delayMin) {
        testPrintE("Unexpected maximum delay less than minimum delay");
        testPrintE("  delayMin: %f delayMax: %f", delayMin, delayMax);
        exit(7);
    }
    if (endPass < startPass) {
        testPrintE("Unexpected ending pass before starting pass");
        testPrintE("  startPass: %u endPass: %u", startPass, endPass);
        exit(8);
    }
    if (argc != optind) {
        testPrintE("Unexpected command-line postional argument");
        testPrintE("  %s [-s start_pass] [-e end_pass] [-d duration]",
            basename(argv[0]));
        exit(9);
    }
    testPrintI("duration: %g", duration);
    testPrintI("startPass: %u", startPass);
    testPrintI("endPass: %u", endPass);
    testPrintI("delayMin: %f", delayMin);
    testPrintI("delayMax: %f", delayMax);

    init();

    // For each pass
    gettimeofday(&startTime, NULL);
    for (pass = startPass; pass <= endPass; pass++) {
        // Stop if duration of work has already been performed
        gettimeofday(&currentTime, NULL);
        delta = tvDelta(&startTime, &currentTime);
        if (tv2double(&delta) > duration) { break; }

        testPrintI("==== Starting pass: %u", pass);

        // Use a pass dependent sequence of random numbers
        srand48(pass);

        // Load WiFi Driver
        randBind(&availCPU, &cpu);
        if ((rv = wifi_load_driver()) != 0) {
            testPrintE("CPU: %i wifi_load_driver() failed, rv: %i\n",
                cpu, rv);
            exit(20);
        }
        testPrintI("CPU: %i wifi_load_driver succeeded", cpu);

        // Start Supplicant
        randBind(&availCPU, &cpu);
        if ((rv = wifi_start_supplicant(false)) != 0) {
            testPrintE("CPU: %i wifi_start_supplicant() failed, rv: %i\n",
                cpu, rv);
            exit(21);
        }
        testPrintI("CPU: %i wifi_start_supplicant succeeded", cpu);

        // Sleep a random amount of time
        randDelay();

        /*
         * Obtain WiFi Status
         * Half the time skip this step, which helps increase the
         * level of randomization.
         */
        if (testRandBool()) {
            rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STATUS);
            if (rv >= (signed) sizeof(cmd) - 1) {
                testPrintE("Command too long for: %s\n", CMD_STATUS);
                exit(22);
            }
            testExecCmd(cmd);
        }

        // Stop Supplicant
        randBind(&availCPU, &cpu);
        if ((rv = wifi_stop_supplicant(false)) != 0) {
            testPrintE("CPU: %i wifi_stop_supplicant() failed, rv: %i\n",
                cpu, rv);
            exit(23);
        }
        testPrintI("CPU: %i wifi_stop_supplicant succeeded", cpu);

        // Unload WiFi Module
        randBind(&availCPU, &cpu);
        if ((rv = wifi_unload_driver()) != 0) {
            testPrintE("CPU: %i wifi_unload_driver() failed, rv: %i\n",
                cpu, rv);
            exit(24);
        }
        testPrintI("CPU: %i wifi_unload_driver succeeded", cpu);

        testPrintI("==== Completed pass: %u", pass);
    }

    // If needed restore WiFi driver to state it was in at the
    // start of the test.  It is assumed that it the driver
    // was loaded, then the wpa_supplicant was also running.
    if (driverLoadedAtStart) {
        // Load driver
        if ((rv = wifi_load_driver()) != 0) {
            testPrintE("main load driver failed, rv: %i", rv);
            exit(25);
        }

        // Start supplicant
        if ((rv = wifi_start_supplicant(false)) != 0) {
            testPrintE("main start supplicant failed, rv: %i", rv);
            exit(26);
        }

        // Obtain WiFi Status
        rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STATUS);
        if (rv >= (signed) sizeof(cmd) - 1) {
            testPrintE("Command too long for: %s\n", CMD_STATUS);
            exit(22);
        }
        testExecCmd(cmd);
    }

    // Start framework
    rv = snprintf(cmd, sizeof(cmd), "%s", CMD_START_FRAMEWORK);
    if (rv >= (signed) sizeof(cmd) - 1) {
        testPrintE("Command too long for: %s\n", CMD_START_FRAMEWORK);
        exit(27);
    }
    testExecCmd(cmd);

    testPrintI("Successfully completed %u passes", pass - startPass);

    return 0;
}
Beispiel #12
0
int testTagData(void) {
    SockInfo sock0;
    SockInfo sock1;
    int res;
    int total_errors = 0;
    int ctrl_fd = -1;
    int dev_fd = -1;
    const uint64_t invalid_tag1 = 0x0000000100000001llu;
    uint64_t valid_tag1;
    uint64_t valid_tag2;
    uint64_t max_uint_tag = 0xffffffff00000000llu;
    uid_t fake_uid;
    uid_t fake_uid2;
    const char *test_name;
    uid_t my_uid = getuid();
    pid_t my_pid = getpid();
    const int max_tags = 5;

    srand48(my_pid * my_uid);
    /* Adjust fake UIDs and tags so that multiple instances can run in parallel. */
    fake_uid = testRand();
    fake_uid2 = testRand();
    valid_tag1 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
    valid_tag2 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
    valid_tag2 &= 0xffffff00ffffffffllu;  // Leave some room to make counts visible.
    testSetLogCatTag(LOG_TAG);

    testPrintI("** %s ** ============================", __FUNCTION__);
    testPrintI("* start: pid=%lu uid=%lu uid1=0x%lx/%lu uid2=0x%lx/%lu"
               " tag1=0x%llx/%llu tag2=0x%llx/%llu",
               my_pid, my_uid, fake_uid, fake_uid, fake_uid2, fake_uid2,
               valid_tag1, valid_tag1, valid_tag2, valid_tag2);

    // ---------------
    test_name = "kernel has qtaguid";
    testPrintI("* test: %s ", test_name);
    ctrl_fd = openCtrl();
    if (ctrl_fd < 0) {
        testPrintE("qtaguid ctrl open failed: %s", strerror(errno));
        return 1;
    }
    close(ctrl_fd);
    dev_fd = open("/dev/xt_qtaguid", O_RDONLY);
    if (dev_fd < 0) {
        testPrintE("! %s: qtaguid dev open failed: %s", test_name, strerror(errno));
        total_errors++;
    }
    // ---------------
    test_name = "delete command doesn't fail";
    testPrintI("* test: %s", test_name);
    res = doCtrlCommand("d 0 %u", fake_uid);
    if (res < 0) {
            testPrintE("! %s: Unexpected results", test_name);
            total_errors++;
    }

    res = doCtrlCommand("d 0 %u", fake_uid2);
    if (res < 0) {
            testPrintE("! %s: Unexpected results", test_name);
            total_errors++;
    }

    res = doCtrlCommand("d 0 %u", my_uid);
    if (res < 0) {
            testPrintE("! %s: Unexpected results", test_name);
            total_errors++;
    }

    // ---------------
    test_name = "setup sock0 and addr via tag";
    testPrintI("* test: %s", test_name);
    if (sock0.setup(valid_tag1)) {
        testPrintE("socket setup failed: %s", strerror(errno));
        return 1;
    }
    // ---------------
    test_name = "setup sock1 and addr via tag";
    testPrintI("* test: %s", test_name);
    if (sock1.setup(valid_tag1)) {
        testPrintE("socket setup failed: %s", strerror(errno));
        return 1;
    }
    // ---------------
    test_name = "setup tag limit";
    testPrintI("* test: %s ", test_name);
    char *max_tags_str;
    asprintf(&max_tags_str, "%d", max_tags);
    res = writeModuleParam("max_sock_tags", max_tags_str);
    if (res < 0) {
        testPrintE("! %s: Unexpected results", test_name);
        free(max_tags_str);
        return 1;
    }

    // ---------------
    test_name = "tag quota reach limit";
    testPrintI("* test: %s", test_name);
    for (int cnt = 0; cnt < max_tags; cnt++ ) {
        uint64_t new_tag = valid_tag2 + ((uint64_t)cnt << 32);
        res = doCtrlCommand("t %d %llu %u", sock0.fd, new_tag , fake_uid2);
        if (res < 0) {
                testPrintE("! %s: Unexpected results", test_name);
                total_errors++;
        }
        if (!sock0.checkTag(new_tag, fake_uid2)) {
                testPrintE("! %s: Unexpected results: tag not found", test_name);
                total_errors++;
        }
    }
    test_name = "tag quota go over limit";
    testPrintI("* test: %s", test_name);
    {
        uint64_t new_tag = valid_tag2 + ((uint64_t)max_tags << 32);
        res = doCtrlCommand("t %d %llu %u", sock0.fd, new_tag , fake_uid2);
        if (res > 0) {
                testPrintE("! %s: Unexpected results", test_name);
                total_errors++;
        }
        if (!sock0.checkTag(valid_tag2 + (((uint64_t)max_tags - 1) << 32), fake_uid2)) {
                testPrintE("! %s: Unexpected results: tag not found", test_name);
                total_errors++;
        }
    }

    // ---------------
    test_name = "valid untag";
    testPrintI("* test: %s", test_name);
    res = doCtrlCommand("u %d", sock0.fd);
    if (res < 0) {
        testPrintE("! %s: Unexpected results", test_name);
        total_errors++;
    }
    if (sock0.checkTag(valid_tag2 + (((uint64_t)max_tags - 1) << 32), fake_uid2)) {
        testPrintE("! %s: Unexpected results: tag should not be there", test_name);
        total_errors++;
    }

    // ---------------
    test_name = "tag after untag shouldn't free up max tags";
    testPrintI("* test: %s", test_name);
    {
        uint64_t new_tag = valid_tag2 + ((uint64_t)max_tags << 32);
        res = doCtrlCommand("t %d %llu %u", sock0.fd, new_tag , fake_uid2);
        if (res > 0) {
                testPrintE("! %s: Unexpected results", test_name);
                total_errors++;
        }
        if (sock0.checkTag(valid_tag2 + ((uint64_t)max_tags << 32), fake_uid2)) {
            testPrintE("! %s: Unexpected results: tag should not be there", test_name);
            total_errors++;
        }
    }

    // ---------------
    test_name = "delete one tag";
    testPrintI("* test: %s", test_name);
    {
            uint64_t new_tag = valid_tag2 + (((uint64_t)max_tags / 2) << 32);
            res = doCtrlCommand("d %llu %u", new_tag, fake_uid2);
            if (res < 0) {
                    testPrintE("! %s: Unexpected results", test_name);
                    total_errors++;
            }
    }

    // ---------------
    test_name = "2 tags after 1 delete pass/fail";
    testPrintI("* test: %s", test_name);
    {
        uint64_t new_tag;
        new_tag = valid_tag2 + (((uint64_t)max_tags + 1 ) << 32);
        res = doCtrlCommand("t %d %llu %u", sock0.fd, new_tag , fake_uid2);
        if (res < 0) {
                testPrintE("! %s: Unexpected results", test_name);
                total_errors++;
        }
        if (!sock0.checkTag(valid_tag2 + (((uint64_t)max_tags + 1) << 32), fake_uid2)) {
            testPrintE("! %s: Unexpected results: tag not found", test_name);
            total_errors++;
        }

        new_tag = valid_tag2 + (((uint64_t)max_tags + 2 ) << 32);
        res = doCtrlCommand("t %d %llu %u", sock0.fd, new_tag , fake_uid2);
        if (res > 0) {
                testPrintE("! %s: Unexpected results", test_name);
                total_errors++;
        }
        if (sock0.checkTag(valid_tag2 + (((uint64_t)max_tags + 2) << 32), fake_uid2)) {
            testPrintE("! %s: Unexpected results: tag should not be there", test_name);
            total_errors++;
        }
    }

    /* TODO(jpa): test tagging two different sockets with same tags and
     * check refcounts  the tag_node should be +2
     */

    // ---------------
    if (total_errors) {
        testPrintE("! Errors found");
    } else {
        testPrintI("No Errors found");
    }

done:
    if (dev_fd >= 0) {
        close(dev_fd);
    }
    if (ctrl_fd >= 0) {
        close(ctrl_fd);
    }
    return total_errors;
}
Beispiel #13
0
/*----------------------------------------------------------------*/
int testSocketTagging(void) {
    SockInfo sock0;
    SockInfo sock1;
    int res;
    int total_errors = 0;
    int ctrl_fd = -1;
    int dev_fd = -1;
    const uint64_t invalid_tag1 = 0x0000000100000001llu;
    uint64_t valid_tag1;
    uint64_t valid_tag2;
    uint64_t max_uint_tag = 0xffffffff00000000llu;
    uid_t fake_uid;
    uid_t fake_uid2;
    const char *test_name;
    uid_t my_uid = getuid();
    pid_t my_pid = getpid();

    srand48(my_pid * my_uid);
    /* Adjust fake UIDs and tags so that multiple instances can run in parallel. */
    fake_uid = testRand();
    fake_uid2 = testRand();
    valid_tag1 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
    valid_tag2 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
    max_uint_tag = 1llu << 63 | (((uint64_t)my_pid << 48) ^ max_uint_tag);
    testSetLogCatTag(LOG_TAG);

    testPrintI("** %s ** ============================", __FUNCTION__);
    testPrintI("* start: pid=%lu uid=%lu uid1=0x%lx/%lu uid2=0x%lx/%lu"
               " tag1=0x%llx/%llu tag2=0x%llx/%llu",
               my_pid, my_uid, fake_uid, fake_uid, fake_uid2, fake_uid2,
               valid_tag1, valid_tag1, valid_tag2, valid_tag2);

    // ---------------
    test_name = "kernel has qtaguid";
    testPrintI("* test: %s ", test_name);
    ctrl_fd = openCtrl();
    if (ctrl_fd < 0) {
        testPrintE("qtaguid ctrl open failed: %s", strerror(errno));
        total_errors++;
        goto done;
    }
    close(ctrl_fd);
    dev_fd = open("/dev/xt_qtaguid", O_RDONLY);
    if (dev_fd < 0) {
        testPrintE("qtaguid dev open failed: %s", strerror(errno));
        total_errors++;
    }
    // ---------------
    test_name = "delete command doesn't fail";
    testPrintI("* test: %s", test_name);
    res = doCtrlCommand("d 0 %u", fake_uid);
    if (res < 0) {
            testPrintE("! %s: Unexpected results", test_name);
            total_errors++;
    }

    res = doCtrlCommand("d 0 %u", fake_uid2);
    if (res < 0) {
            testPrintE("! %s: Unexpected results", test_name);
            total_errors++;
    }

    res = doCtrlCommand("d 0 %u", my_uid);
    if (res < 0) {
            testPrintE("! %s: Unexpected results", test_name);
            total_errors++;
    }
    // ---------------
    test_name = "setup sock0 and addr via tag";
    testPrintI("* test: %s", test_name);
    if (sock0.setup(valid_tag1) < 0) {
        testPrintE("socket setup failed: %s", strerror(errno));
        total_errors++;
        goto done;

    }
    // ---------------
    test_name = "setup sock1 and addr via tag";
    testPrintI("* test: %s", test_name);
    if (sock1.setup(valid_tag1) < 0) {
        testPrintE("socket setup failed: %s", strerror(errno));
        total_errors++;
        goto done;
    }
    // ---------------
    test_name = "insufficient args. Expected failure";
    testPrintI("* test: %s", test_name);
    res = doCtrlCommand("t");
    if (res > 0) {
        testPrintE("! %s: Unexpected results", test_name);
        total_errors++;
    }

    // ---------------
    test_name = "bad command. Expected failure";
    testPrintI("* test: %s", test_name);
    res = doCtrlCommand("?");
    if (res > 0) {
            testPrintE("! %s: Unexpected results", test_name);
        total_errors++;
    }

    // ---------------
    test_name = "no tag, no uid";
    testPrintI("* test: %s", test_name);
    res = doCtrlCommand("t %d", sock0.fd);
    if (res < 0) {
        testPrintE("! %s: Unexpected results", test_name);
        total_errors++;
    }
    if (!sock0.checkTag(0, my_uid)) {
        testPrintE("! %s: Unexpected results: tag not found", test_name);
        total_errors++;
    }

    // ---------------
    test_name = "invalid tag. Expected failure";
    testPrintI("* test: %s", test_name);
    res = doCtrlCommand("t %d %llu", sock0.fd, invalid_tag1);
    if (res > 0) {
        testPrintE("! %s: Unexpected results", test_name);
        total_errors++;
    }
    if (sock0.checkTag(invalid_tag1, my_uid)) {
        testPrintE("! %s: Unexpected results: tag should not be there", test_name);
        total_errors++;
    }

    // ---------------
    test_name = "valid tag with no uid";
    testPrintI("* test: %s", test_name);
    res = doCtrlCommand("t %d %llu", sock0.fd, valid_tag1);
    if (res < 0) {
        testPrintE("! %s: Unexpected results", test_name);
        total_errors++;
    }
    if (!sock0.checkTag(valid_tag1, my_uid)) {
        testPrintE("! %s: Unexpected results: tag not found", test_name);
        total_errors++;
    }
    // ---------------
    test_name = "valid untag";
    testPrintI("* test: %s", test_name);
    res = doCtrlCommand("u %d", sock0.fd);
    if (res < 0) {
        testPrintE("! %s: Unexpected results", test_name);
        total_errors++;
    }
    if (sock0.checkTag(valid_tag1, my_uid)) {
        testPrintE("! %s: Unexpected results: tag not removed", test_name);
        total_errors++;
    }

    // ---------------
    test_name = "valid 1st tag";
    testPrintI("* test: %s", test_name);
    res = doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid);
    if (res < 0) {
        testPrintE("! %s: Unexpected results", test_name);
        total_errors++;
    }
    if (!sock0.checkTag(valid_tag2, fake_uid)) {
        testPrintE("! %s: Unexpected results: tag not found", test_name);
        total_errors++;
    }

    // ---------------
    test_name = "valid re-tag";
    testPrintI("* test: %s", test_name);
    res = doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid);
    if (res < 0) {
        testPrintE("! %s: Unexpected results", test_name);
        total_errors++;
    }
    if (!sock0.checkTag(valid_tag2, fake_uid)) {
        testPrintE("! %s: Unexpected results: tag not found", test_name);
        total_errors++;
    }

    // ---------------
    test_name = "valid re-tag with acct_tag change";
    testPrintI("* test: %s", test_name);
    res = doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag1, fake_uid);
    if (res < 0) {
        testPrintE("! %s: Unexpected results", test_name);
        total_errors++;
    }
    if (!sock0.checkTag(valid_tag1, fake_uid)) {
        testPrintE("! %s: Unexpected results: tag not found", test_name);
        total_errors++;
    }

    // ---------------
    test_name = "re-tag with uid change";
    testPrintI("* test: %s", test_name);
    res = doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid2);
    if (res < 0) {
        testPrintE("! %s: Unexpected results", test_name);
        total_errors++;
    }
    if (!sock0.checkTag(valid_tag2, fake_uid2)) {
        testPrintE("! %s: Unexpected results: tag not found", test_name);
        total_errors++;
    }

    // ---------------
    test_name = "valid 64bit acct tag";
    testPrintI("* test: %s", test_name);
    res = doCtrlCommand("t %d %llu", sock0.fd, max_uint_tag);
    if (res < 0) {
        testPrintE("! %s: Unexpected results", test_name);
        total_errors++;
    }
    if (!sock0.checkTag(max_uint_tag, my_uid)) {
        testPrintE("! %s: Unexpected results: tag not found", test_name);
        total_errors++;
    }

    // ---------------
    test_name = "tag another socket";
    testPrintI("* test: %s", test_name);
    res = doCtrlCommand("t %d %llu %u", sock1.fd, valid_tag1, fake_uid2);
    if (res < 0) {
        testPrintE("! %s: Unexpected results", test_name);
        total_errors++;
    }
    if (!sock1.checkTag(valid_tag1, fake_uid2)) {
        testPrintE("! %s: Unexpected results: tag not found", test_name);
        total_errors++;
    }

    // ---------------
    test_name = "valid untag";
    testPrintI("* test: %s", test_name);
    res = doCtrlCommand("u %d", sock0.fd);
    if (res < 0) {
        testPrintE("! %s: Unexpected results", test_name);
        total_errors++;
    }
    if (sock0.checkTag(max_uint_tag, fake_uid)) {
        testPrintE("! %s: Unexpected results: tag should not be there", test_name);
        total_errors++;
    }
    if (!sock1.checkTag(valid_tag1, fake_uid2)) {
        testPrintE("! %s: Unexpected results: tag not found", test_name);
        total_errors++;
    }
    res = doCtrlCommand("u %d", sock1.fd);
    if (res < 0) {
        testPrintE("! %s: Unexpected results", test_name);
        total_errors++;
    }
    if (sock1.checkTag(valid_tag1, fake_uid2)) {
        testPrintE("! %s: Unexpected results: tag should not be there", test_name);
        total_errors++;
    }

    // ---------------
    test_name = "invalid sock0.fd. Expected failure";
    testPrintI("* test: %s", test_name);
    close(sock0.fd);
    res = doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag1, my_uid);
    if (res > 0) {
            testPrintE("! %s: Unexpected results", test_name);
        total_errors++;
    }
    if (sock0.checkTag(valid_tag1, my_uid)) {
        testPrintE("! %s: Unexpected results: tag should not be there", test_name);
        total_errors++;
    }

    // ---------------
    test_name = "invalid untag. Expected failure";
    testPrintI("* test: %s", test_name);
    close(sock1.fd);
    res = doCtrlCommand("u %d", sock1.fd);
    if (res > 0) {
        testPrintE("! %s: Unexpected results", test_name);
        total_errors++;
    }

    if (total_errors) {
        testPrintE("! Errors found");
    } else {
        testPrintI("No Errors found");
    }

done:
    if (dev_fd >= 0) {
        close(dev_fd);
    }
    if (ctrl_fd >= 0) {
        close(ctrl_fd);
    }
    return total_errors;
}
Beispiel #14
0
TEST(pcmtest, GetSoundDevs) {
    int err = getSndDev(pcms);
    testPrintI(" DEVICES = PCMS:%u CARDS:%u MIXERS:%u TIMERS:%u",
               pcms, cards, mixers, timers);
    ASSERT_EQ(0, err);
}