/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <sstream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <gtest/gtest.h>
#include <lmkd.h>
#include <liblmkd_utils.h>
#include <log/log_properties.h>
#include <private/android_filesystem_config.h>

using namespace android::base;

#define INKERNEL_MINFREE_PATH "/sys/module/lowmemorykiller/parameters/minfree"
#define LMKDTEST_RESPAWN_FLAG "LMKDTEST_RESPAWN"

#define LMKD_LOGCAT_MARKER "lowmemorykiller"
#define LMKD_KILL_MARKER_TEMPLATE LMKD_LOGCAT_MARKER ": Killing '%s'"
#define OOM_MARKER "Out of memory"
#define OOM_KILL_MARKER "Killed process"
#define MIN_LOG_SIZE 100

#define ONE_MB (1 << 20)

/* Test constant parameters */
#define OOM_ADJ_MAX 1000
#define OOM_ADJ_MIN 0
#define OOM_ADJ_STEP 100
#define STEP_COUNT ((OOM_ADJ_MAX - OOM_ADJ_MIN) / OOM_ADJ_STEP + 1)

#define ALLOC_STEP (ONE_MB)
#define ALLOC_DELAY 1000

/* Utility functions */
std::string readCommand(const std::string& command) {
    FILE* fp = popen(command.c_str(), "r");
    std::string content;
    ReadFdToString(fileno(fp), &content);
    pclose(fp);
    return content;
}

std::string readLogcat(const std::string& marker) {
    std::string content = readCommand("logcat -d -b all");
    size_t pos = content.find(marker);
    if (pos == std::string::npos) return "";
    content.erase(0, pos);
    return content;
}

bool writeFile(const std::string& file, const std::string& string) {
    if (getuid() == static_cast<unsigned>(AID_ROOT)) {
        return WriteStringToFile(string, file);
    }
    return string == readCommand(
        "echo -n '" + string + "' | su root tee " + file + " 2>&1");
}

bool writeKmsg(const std::string& marker) {
    return writeFile("/dev/kmsg", marker);
}

std::string getTextAround(const std::string& text, size_t pos,
                          size_t lines_before, size_t lines_after) {
    size_t start_pos = pos;

    // find start position
    // move up lines_before number of lines
    while (lines_before > 0 &&
           (start_pos = text.rfind('\n', start_pos)) != std::string::npos) {
        lines_before--;
    }
    // move to the beginning of the line
    start_pos = text.rfind('\n', start_pos);
    start_pos = (start_pos == std::string::npos) ? 0 : start_pos + 1;

    // find end position
    // move down lines_after number of lines
    while (lines_after > 0 &&
           (pos = text.find('\n', pos)) != std::string::npos) {
        pos++;
        lines_after--;
    }
    return text.substr(start_pos, (pos == std::string::npos) ?
                       std::string::npos : pos - start_pos);
}

bool getExecPath(std::string &path) {
    char buf[PATH_MAX + 1];
    int ret = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
    if (ret < 0) {
        return false;
    }
    buf[ret] = '\0';
    path = buf;
    return true;
}

/* Child synchronization primitives */
#define STATE_INIT 0
#define STATE_CHILD_READY 1
#define STATE_PARENT_READY 2

struct state_sync {
    pthread_mutex_t mutex;
    pthread_cond_t condition;
    int state;
};

struct state_sync * init_state_sync_obj() {
    struct state_sync *ssync;

    ssync = (struct state_sync*)mmap(NULL, sizeof(struct state_sync),
                PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
    if (ssync == MAP_FAILED) {
        return NULL;
    }

    pthread_mutexattr_t mattr;
    pthread_mutexattr_init(&mattr);
    pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
    pthread_mutex_init(&ssync->mutex, &mattr);

    pthread_condattr_t cattr;
    pthread_condattr_init(&cattr);
    pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED);
    pthread_cond_init(&ssync->condition, &cattr);

    ssync->state = STATE_INIT;
    return ssync;
}

void destroy_state_sync_obj(struct state_sync *ssync) {
    pthread_cond_destroy(&ssync->condition);
    pthread_mutex_destroy(&ssync->mutex);
    munmap(ssync, sizeof(struct state_sync));
}

void signal_state(struct state_sync *ssync, int state) {
    pthread_mutex_lock(&ssync->mutex);
    ssync->state = state;
    pthread_cond_signal(&ssync->condition);
    pthread_mutex_unlock(&ssync->mutex);
}

void wait_for_state(struct state_sync *ssync, int state) {
    pthread_mutex_lock(&ssync->mutex);
    while (ssync->state != state) {
        pthread_cond_wait(&ssync->condition, &ssync->mutex);
    }
    pthread_mutex_unlock(&ssync->mutex);
}

/* Memory allocation and data sharing */
struct shared_data {
    size_t allocated;
    bool finished;
    size_t total_size;
    size_t step_size;
    size_t step_delay;
    int oomadj;
};

volatile void *gptr;
void add_pressure(struct shared_data *data) {
    volatile void *ptr;
    size_t allocated_size = 0;

    data->finished = false;
    while (allocated_size < data->total_size) {
        ptr = mmap(NULL, data->step_size, PROT_READ | PROT_WRITE,
                MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
        if (ptr != MAP_FAILED) {
            /* create ptr aliasing to prevent compiler optimizing the access */
            gptr = ptr;
            /* make data non-zero */
            memset((void*)ptr, (int)(allocated_size + 1), data->step_size);
            allocated_size += data->step_size;
            data->allocated = allocated_size;
        }
        usleep(data->step_delay);
    }
    data->finished = (allocated_size >= data->total_size);
}

/* Memory stress test main body */
void runMemStressTest() {
    struct shared_data *data;
    struct state_sync *ssync;
    int sock;
    pid_t pid;
    uid_t uid = getuid();

    ASSERT_FALSE((sock = lmkd_connect()) < 0)
        << "Failed to connect to lmkd process, err=" << strerror(errno);

    /* allocate shared memory to communicate params with a child */
    data = (struct shared_data*)mmap(NULL, sizeof(struct shared_data),
                PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
    ASSERT_FALSE(data == MAP_FAILED) << "Memory allocation failure";
    data->total_size = (size_t)-1; /* allocate until killed */
    data->step_size = ALLOC_STEP;
    data->step_delay = ALLOC_DELAY;

    /* allocate state sync object */
    ASSERT_FALSE((ssync = init_state_sync_obj()) == NULL)
        << "Memory allocation failure";

    /* run the test gradually decreasing oomadj */
    data->oomadj = OOM_ADJ_MAX;
    while (data->oomadj >= OOM_ADJ_MIN) {
        ASSERT_FALSE((pid = fork()) < 0)
            << "Failed to spawn a child process, err=" << strerror(errno);
        if (pid != 0) {
            /* Parent */
            struct lmk_procprio params;
            /* wait for child to start and get ready */
            wait_for_state(ssync, STATE_CHILD_READY);
            params.pid = pid;
            params.uid = uid;
            params.oomadj = data->oomadj;
            ASSERT_FALSE(lmkd_register_proc(sock, &params) < 0)
                << "Failed to communicate with lmkd, err=" << strerror(errno);
            // signal the child it can proceed
            signal_state(ssync, STATE_PARENT_READY);
            waitpid(pid, NULL, 0);
            if (data->finished) {
                GTEST_LOG_(INFO) << "Child [pid=" << pid << "] allocated "
                                 << data->allocated / ONE_MB << "MB";
            } else {
                GTEST_LOG_(INFO) << "Child [pid=" << pid << "] allocated "
                                 << data->allocated / ONE_MB
                                 << "MB before being killed";
            }
            data->oomadj -= OOM_ADJ_STEP;
        } else {
            /* Child */
            pid = getpid();
            GTEST_LOG_(INFO) << "Child [pid=" << pid
                             << "] is running at oomadj="
                             << data->oomadj;
            data->allocated = 0;
            data->finished = false;
            ASSERT_FALSE(create_memcg(uid, pid) != 0)
                << "Child [pid=" << pid << "] failed to create a cgroup";
            signal_state(ssync, STATE_CHILD_READY);
            wait_for_state(ssync, STATE_PARENT_READY);
            add_pressure(data);
            /* should not reach here, child should be killed by OOM/LMK */
            FAIL() << "Child [pid=" << pid << "] was not killed";
            break;
        }
    }
    destroy_state_sync_obj(ssync);
    munmap(data, sizeof(struct shared_data));
    close(sock);
}

TEST(lmkd, check_for_oom) {
    // test requirements
    //   userdebug build
    if (!__android_log_is_debuggable()) {
        GTEST_LOG_(INFO) << "Must be userdebug build, terminating test";
        return;
    }
    // check if in-kernel LMK driver is present
    if (!access(INKERNEL_MINFREE_PATH, W_OK)) {
        GTEST_LOG_(INFO) << "Must not have kernel lowmemorykiller driver,"
                         << " terminating test";
        return;
    }

    // if respawned test process then run the test and exit (no analysis)
    if (getenv(LMKDTEST_RESPAWN_FLAG) != NULL) {
        runMemStressTest();
        return;
    }

    // Main test process
    // mark the beginning of the test
    std::string marker = StringPrintf(
        "LMKD test start %lu\n", static_cast<unsigned long>(time(nullptr)));
    ASSERT_TRUE(writeKmsg(marker));

    // get executable complete path
    std::string test_path;
    ASSERT_TRUE(getExecPath(test_path));

    std::string test_output;
    if (getuid() != static_cast<unsigned>(AID_ROOT)) {
        // if not root respawn itself as root and capture output
        std::string command = StringPrintf(
            "%s=true su root %s 2>&1", LMKDTEST_RESPAWN_FLAG,
            test_path.c_str());
        std::string test_output = readCommand(command);
        GTEST_LOG_(INFO) << test_output;
    } else {
        // main test process is root, run the test
        runMemStressTest();
    }

    // Analyze results
    // capture logcat containind kernel logs
    std::string logcat_out = readLogcat(marker);

    // 1. extract LMKD kills from logcat output, count kills
    std::stringstream kill_logs;
    int hit_count = 0;
    size_t pos = 0;
    marker = StringPrintf(LMKD_KILL_MARKER_TEMPLATE, test_path.c_str());

    while (true) {
        if ((pos = logcat_out.find(marker, pos)) != std::string::npos) {
            kill_logs << getTextAround(logcat_out, pos, 0, 1);
            pos += marker.length();
            hit_count++;
        } else {
            break;
        }
    }
    GTEST_LOG_(INFO) << "====Logged kills====" << std::endl
                     << kill_logs.str();
    EXPECT_TRUE(hit_count == STEP_COUNT) << "Number of kills " << hit_count
                                         << " is less than expected "
                                         << STEP_COUNT;

    // 2. check kernel logs for OOM kills
    pos = logcat_out.find(OOM_MARKER);
    bool oom_detected = (pos != std::string::npos);
    bool oom_kill_detected = (oom_detected &&
        logcat_out.find(OOM_KILL_MARKER, pos) != std::string::npos);

    EXPECT_FALSE(oom_kill_detected) << "OOM kill is detected!";
    if (oom_detected || oom_kill_detected) {
        // capture logcat with logs around all OOMs
        pos = 0;
        while ((pos = logcat_out.find(OOM_MARKER, pos)) != std::string::npos) {
            GTEST_LOG_(INFO) << "====Logs around OOM====" << std::endl
                             << getTextAround(logcat_out, pos,
                                    MIN_LOG_SIZE / 2, MIN_LOG_SIZE / 2);
            pos += strlen(OOM_MARKER);
        }
    }

    // output complete logcat with kernel (might get truncated)
    GTEST_LOG_(INFO) << "====Complete logcat output====" << std::endl
                     << logcat_out;
}

