#include <gtest/gtest.h>
#include <thread>
#include <vector>
#include <fcntl.h>
extern "C" {
#include "gr_api.h"
#include "gr_errno.h"
}
#define TEST_LOG_DIR "./test_log"
#define TEST_DIR "complexdir"
#define TEST_FILE1 "complexfile1"
#define TEST_FILE2 "complexfile2"
#define ONE_GB 1024 * 1024 * 1024
#define SERVER_ADDR "127.0.0.1:19225"
int errorcode = 0;
const char *errormsg = NULL;
gr_instance_handle g_inst_handle1 = NULL;
gr_instance_handle g_inst_handle2 = NULL;
gr_instance_handle g_inst_handle3 = NULL;
gr_instance_handle g_inst_handle4 = NULL;
gr_vfs_handle g_vfs_handle1;
gr_vfs_handle g_vfs_handle2;
gr_vfs_handle g_vfs_handle3;
gr_vfs_handle g_vfs_handle4;
gr_file_handle file_handle1;
gr_file_handle file_handle2;
gr_file_handle file_handle3;
gr_file_handle file_handle4;
gr_param_t g_gr_param;
class ComplexGRApiTest : public ::testing::Test {
protected:
void SetUp() override {
strcpy(g_gr_param.log_home, "./testlog");
g_gr_param.log_level = 255;
g_gr_param.log_backup_file_count = 100;
g_gr_param.log_max_file_size = ONE_GB;
int result = gr_init(g_gr_param);
ASSERT_EQ(result, GR_SUCCESS) << "Failed to initialize logger";
EXPECT_EQ(gr_create_inst(SERVER_ADDR, &g_inst_handle1), GR_SUCCESS);
EXPECT_EQ(gr_create_inst(SERVER_ADDR, &g_inst_handle2), GR_SUCCESS);
EXPECT_EQ(gr_create_inst(SERVER_ADDR, &g_inst_handle3), GR_SUCCESS);
EXPECT_EQ(gr_create_inst(SERVER_ADDR, &g_inst_handle4), GR_SUCCESS);
gr_vfs_create(g_inst_handle1, TEST_DIR, 0);
EXPECT_EQ(gr_vfs_mount(g_inst_handle1, TEST_DIR, &g_vfs_handle1), GR_SUCCESS);
EXPECT_EQ(gr_vfs_mount(g_inst_handle2, TEST_DIR, &g_vfs_handle2), GR_SUCCESS);
EXPECT_EQ(gr_vfs_mount(g_inst_handle1, TEST_DIR, &g_vfs_handle3), GR_SUCCESS);
EXPECT_EQ(gr_vfs_mount(g_inst_handle2, TEST_DIR, &g_vfs_handle4), GR_SUCCESS);
EXPECT_EQ(gr_file_create(g_vfs_handle1, TEST_FILE1, NULL), GR_SUCCESS);
EXPECT_EQ(gr_file_create(g_vfs_handle2, TEST_FILE2, NULL), GR_SUCCESS);
EXPECT_EQ(gr_file_open(g_vfs_handle1, TEST_FILE1, O_RDWR | O_SYNC, &file_handle1), GR_SUCCESS);
EXPECT_EQ(gr_file_open(g_vfs_handle2, TEST_FILE2, O_RDWR | O_SYNC, &file_handle2), GR_SUCCESS);
EXPECT_EQ(gr_file_open(g_vfs_handle3, TEST_FILE1, O_RDWR | O_SYNC, &file_handle3), GR_SUCCESS);
EXPECT_EQ(gr_file_open(g_vfs_handle4, TEST_FILE2, O_RDWR | O_SYNC, &file_handle4), GR_SUCCESS);
}
void TearDown() override {
EXPECT_EQ(gr_file_close(g_vfs_handle1, &file_handle1, true), GR_SUCCESS);
EXPECT_EQ(gr_file_close(g_vfs_handle1, &file_handle2, true), GR_SUCCESS);
#ifndef ENABLE_WORM
EXPECT_EQ(gr_file_delete(g_vfs_handle1, TEST_FILE1, 0), GR_SUCCESS);
EXPECT_EQ(gr_file_delete(g_vfs_handle1, TEST_FILE2, 0), GR_SUCCESS);
#endif
EXPECT_EQ(gr_vfs_unmount(&g_vfs_handle1), GR_SUCCESS);
EXPECT_EQ(gr_vfs_unmount(&g_vfs_handle2), GR_SUCCESS);
#ifndef ENABLE_WORM
EXPECT_EQ(gr_vfs_delete(g_inst_handle1, TEST_DIR, 1), GR_SUCCESS);
#endif
}
};
void writeData(gr_file_handle *file_handle, gr_vfs_handle vfs_handle, const char* data, size_t size, int64_t offset) {
EXPECT_EQ(gr_file_pwrite(vfs_handle, file_handle, data, size, offset), size);
}
void readData(gr_file_handle file_handle, gr_vfs_handle vfs_handle, char* buffer, size_t size, int64_t offset) {
EXPECT_EQ(gr_file_pread(vfs_handle, file_handle, buffer, size, offset), size);
}
TEST_F(ComplexGRApiTest, TestConcurrentReadWrite) {
const int data_size1 = 512 * 1024;
const int data_size2 = 256 * 1024;
char *data1 = new char[data_size1];
char *data2 = new char[data_size2];
memset(data1, 'X', data_size1);
memset(data2, 'Y', data_size2);
char *read_buffer1 = new char[data_size1];
char *read_buffer2 = new char[data_size2];
std::vector<std::thread> threads;
threads.emplace_back(writeData, &file_handle1, g_vfs_handle1, data1, data_size1, 0);
threads.emplace_back(writeData, &file_handle2, g_vfs_handle2, data2, data_size2, 0);
sleep(5);
threads.emplace_back(readData, file_handle3, g_vfs_handle3, read_buffer1, data_size1, 0);
threads.emplace_back(readData, file_handle4, g_vfs_handle4, read_buffer2, data_size2, 0);
for (auto& t : threads) {
t.join();
}
EXPECT_EQ(memcmp(data1, read_buffer1, data_size1), 0);
EXPECT_EQ(memcmp(data2, read_buffer2, data_size2), 0);
delete[] data1;
delete[] data2;
delete[] read_buffer1;
delete[] read_buffer2;
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}