/*
 * 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 ": Kill '%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();

    // 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;
    }

    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;
    }

    // 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;
}

