#include <gtest/gtest.h>
#define CR_HOST
#include "../cr.h"
#include "test_data.h"
#if defined(CR_PLATFORM_WIN) || defined(CR_PLATFORM_LINUX)
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
void touch(const char *filename) {
fs::path p = filename;
auto ftime = fs::last_write_time(p);
fs::last_write_time(p, ftime + std::chrono::seconds(1));
}
#else
void touch(const char *filename) {
std::this_thread::sleep_for(std::chrono::seconds(1));
char cmd[1024] = {};
snprintf(cmd, sizeof(cmd), "touch %s", filename);
system(cmd);
}
#endif
TEST(crTest, basic_flow) {
const char *bin = CR_DEPLOY_PATH "/" CR_PLUGIN("test_basic");
using namespace test_basic;
cr_plugin ctx;
test_data data;
ctx.userdata = &data;
EXPECT_EQ(true, cr_plugin_load(ctx, bin));
data.test = test_id::return_version;
EXPECT_EQ(1, cr_plugin_update(ctx));
data.test = test_id::static_local_state_int;
EXPECT_EQ(11, cr_plugin_update(ctx));
data.test = test_id::static_global_state_int;
int saved_global_static = cr_plugin_update(ctx);
EXPECT_EQ(1, saved_global_static);
data.test = test_id::static_local_state_int;
int saved_local_static = cr_plugin_update(ctx);
EXPECT_EQ(12, saved_local_static);
touch(bin);
data.test = test_id::return_version;
EXPECT_EQ(2, cr_plugin_update(ctx));
data.test = test_id::static_global_state_int;
EXPECT_EQ(saved_global_static + 1, cr_plugin_update(ctx));
EXPECT_EQ(saved_global_static + 2, cr_plugin_update(ctx));
data.test = test_id::static_local_state_int;
EXPECT_EQ(saved_local_static + 1, cr_plugin_update(ctx));
EXPECT_EQ(saved_local_static + 2, cr_plugin_update(ctx));
data.test = test_id::heap_data_alloc;
EXPECT_EQ(4096 * 1024, cr_plugin_update(ctx));
EXPECT_EQ(0, cr_plugin_update(ctx));
data.test = test_id::crash_update;
EXPECT_EQ(-1, cr_plugin_update(ctx));
EXPECT_EQ((unsigned int)1, ctx.version);
EXPECT_EQ(CR_SEGFAULT, ctx.failure);
data.test = test_id::return_version;
EXPECT_EQ(1, cr_plugin_update(ctx));
data.test = test_id::static_local_state_int;
EXPECT_EQ(saved_local_static + 1, cr_plugin_update(ctx));
data.test = test_id::static_global_state_int;
EXPECT_EQ(saved_global_static + 1, cr_plugin_update(ctx));
data.test = test_id::heap_data_alloc;
EXPECT_EQ(0, cr_plugin_update(ctx));
touch(bin);
data.test = test_id::return_version;
EXPECT_EQ(2, cr_plugin_update(ctx));
data.test = test_id::heap_data_alloc;
EXPECT_EQ(0, cr_plugin_update(ctx));
data.test = test_id::static_local_state_int;
EXPECT_EQ(saved_local_static + 2, cr_plugin_update(ctx));
data.test = test_id::static_global_state_int;
EXPECT_EQ(saved_global_static + 2, cr_plugin_update(ctx));
data.test = test_id::heap_data_free;
EXPECT_EQ(4096 * 1024, cr_plugin_update(ctx));
EXPECT_EQ(0, cr_plugin_update(ctx));
touch(bin);
data.test = test_id::crash_load;
EXPECT_EQ(-2, cr_plugin_update(ctx));
EXPECT_EQ((unsigned int)2, ctx.version);
EXPECT_EQ(CR_SEGFAULT, ctx.failure);
data.test = test_id::return_version;
EXPECT_EQ(2, cr_plugin_update(ctx));
touch(bin);
data.test = test_id::crash_unload;
EXPECT_EQ(-2, cr_plugin_update(ctx));
EXPECT_EQ((unsigned int)2, ctx.version);
EXPECT_EQ(CR_SEGFAULT, ctx.failure);
data.test = test_id::return_version;
EXPECT_EQ(2, cr_plugin_update(ctx));
data.test = test_id::static_local_state_int;
EXPECT_EQ(saved_local_static + 3, cr_plugin_update(ctx));
data.test = test_id::static_global_state_int;
EXPECT_EQ(saved_global_static + 3, cr_plugin_update(ctx));
cr_plugin_close(ctx);
EXPECT_EQ(ctx.p, nullptr);
EXPECT_EQ(0u, ctx.version);
}