#include <gtest/gtest.h>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <fcntl.h>
extern "C" {
#include "dss_api.h"
}
static const char *GetEnvOrNull(const char *name)
{
const char *val = std::getenv(name);
if (val == nullptr || std::strlen(val) == 0) {
return nullptr;
}
return val;
}
static bool BuildDssSvrPath(char *out, size_t out_size)
{
const char *svr_path_env = GetEnvOrNull("DSS_GTEST_SVR_PATH");
if (svr_path_env != nullptr) {
size_t len = std::strlen(svr_path_env);
if (len + 1 > out_size) {
std::printf("[DSSApiFileTest] DSS_GTEST_SVR_PATH too long, skip business test.\n");
return false;
}
std::memcpy(out, svr_path_env, len + 1);
return true;
}
const char *dss_home = GetEnvOrNull("DSS_HOME");
if (dss_home == nullptr) {
std::printf("[DSSApiFileTest] Neither DSS_GTEST_SVR_PATH nor DSS_HOME set, skip business test.\n");
return false;
}
int n = std::snprintf(out, out_size, "UDS:%s/.dss_unix_d_socket", dss_home);
if (n <= 0 || static_cast<size_t>(n) >= out_size) {
std::printf("[DSSApiFileTest] Failed to build UDS path from DSS_HOME, skip business test.\n");
return false;
}
return true;
}
static bool BuildSubFilePath(const char *base, const char *suffix, char *out, size_t out_size)
{
if (base == nullptr || suffix == nullptr) {
return false;
}
int n = std::snprintf(out, out_size, "%s%s", base, suffix);
if (n <= 0 || static_cast<size_t>(n) >= out_size) {
std::printf("[DSSApiFileTest] Failed to build sub file path from base=%s, suffix=%s.\n", base, suffix);
return false;
}
return true;
}
TEST(DSSApiFileTest, CreateWriteReadRemoveFile)
{
const char *file_base = GetEnvOrNull("DSS_GTEST_FILE_PATH");
if (file_base == nullptr) {
std::printf("[DSSApiFileTest] DSS_GTEST_FILE_PATH not set, skip business test.\n");
return;
}
char svr_path[1024] = {0};
if (!BuildDssSvrPath(svr_path, sizeof(svr_path))) {
return;
}
const char *file_path = file_base;
if (dss_set_svr_path(svr_path) != DSS_SUCCESS) {
std::printf("[DSSApiFileTest] dss_set_svr_path failed (svr_path=%s), skip business test.\n", svr_path);
return;
}
(void)dss_fremove(file_path);
int ret = dss_fcreate(file_path, 0);
if (ret != DSS_SUCCESS) {
std::printf("[DSSApiFileTest] dss_fcreate failed, skip business test.\n");
return;
}
int handle = -1;
ret = dss_fopen(file_path, O_RDWR, &handle);
if (ret != DSS_SUCCESS) {
std::printf("[DSSApiFileTest] dss_fopen failed, skip business test.\n");
(void)dss_fremove(file_path);
return;
}
const char *write_data = "hello dss gtest";
int write_size = static_cast<int>(std::strlen(write_data));
ret = dss_fwrite(handle, write_data, write_size);
ASSERT_EQ(DSS_SUCCESS, ret);
long long seek_ret = dss_fseek(handle, 0, SEEK_SET);
ASSERT_EQ(0, seek_ret);
char read_buf[256] = {0};
int read_size = 0;
ret = dss_fread(handle, read_buf, write_size, &read_size);
ASSERT_EQ(DSS_SUCCESS, ret);
ASSERT_EQ(write_size, read_size);
ASSERT_EQ(0, std::memcmp(read_buf, write_data, write_size));
ret = dss_fclose(handle);
ASSERT_EQ(DSS_SUCCESS, ret);
ret = dss_fremove(file_path);
ASSERT_EQ(DSS_SUCCESS, ret);
}
TEST(DSSApiFileTest, PwritePreadAndTruncate)
{
const char *file_base = GetEnvOrNull("DSS_GTEST_FILE_PATH");
if (file_base == nullptr) {
std::printf("[DSSApiFileTest] DSS_GTEST_FILE_PATH not set, skip business test.\n");
return;
}
char svr_path[1024] = {0};
if (!BuildDssSvrPath(svr_path, sizeof(svr_path))) {
return;
}
char file_path[1024] = {0};
if (!BuildSubFilePath(file_base, "_pwrite", file_path, sizeof(file_path))) {
return;
}
if (dss_set_svr_path(svr_path) != DSS_SUCCESS) {
std::printf("[DSSApiFileTest] dss_set_svr_path failed (svr_path=%s), skip business test.\n", svr_path);
return;
}
(void)dss_fremove(file_path);
int ret = dss_fcreate(file_path, 0);
if (ret != DSS_SUCCESS) {
std::printf("[DSSApiFileTest] dss_fcreate failed for %s, skip business test.\n", file_path);
return;
}
int handle = -1;
ret = dss_fopen(file_path, O_RDWR, &handle);
if (ret != DSS_SUCCESS) {
std::printf("[DSSApiFileTest] dss_fopen failed for %s, skip business test.\n", file_path);
(void)dss_fremove(file_path);
return;
}
const char *block1 = "AAAAA";
const char *block2 = "BBBBB";
int len = 5;
ret = dss_pwrite(handle, block1, len, 0);
ASSERT_EQ(DSS_SUCCESS, ret);
ret = dss_pwrite(handle, block2, len, len);
ASSERT_EQ(DSS_SUCCESS, ret);
char buf[32] = {0};
int read_size = 0;
ret = dss_pread(handle, buf, len, 0, &read_size);
ASSERT_EQ(DSS_SUCCESS, ret);
ASSERT_EQ(len, read_size);
ASSERT_EQ(0, std::memcmp(buf, block1, len));
std::memset(buf, 0, sizeof(buf));
read_size = 0;
ret = dss_pread(handle, buf, len, len, &read_size);
ASSERT_EQ(DSS_SUCCESS, ret);
ASSERT_EQ(len, read_size);
ASSERT_EQ(0, std::memcmp(buf, block2, len));
long long new_len = len;
ret = dss_ftruncate(handle, new_len);
ASSERT_EQ(DSS_SUCCESS, ret);
std::memset(buf, 0, sizeof(buf));
read_size = 0;
ret = dss_pread(handle, buf, len * 2, 0, &read_size);
ASSERT_EQ(DSS_SUCCESS, ret);
ASSERT_EQ(0, std::memcmp(buf, block1, len));
ret = dss_fclose(handle);
ASSERT_EQ(DSS_SUCCESS, ret);
ret = dss_fremove(file_path);
ASSERT_EQ(DSS_SUCCESS, ret);
}
TEST(DSSApiFileTest, CopyAndStatFile)
{
const char *file_base = GetEnvOrNull("DSS_GTEST_FILE_PATH");
if (file_base == nullptr) {
std::printf("[DSSApiFileTest] DSS_GTEST_FILE_PATH not set, skip business test.\n");
return;
}
char svr_path[1024] = {0};
if (!BuildDssSvrPath(svr_path, sizeof(svr_path))) {
return;
}
char src_path[1024] = {0};
char dst_path[1024] = {0};
if (!BuildSubFilePath(file_base, "_copy_src", src_path, sizeof(src_path))) {
return;
}
if (!BuildSubFilePath(file_base, "_copy_dst", dst_path, sizeof(dst_path))) {
return;
}
if (dss_set_svr_path(svr_path) != DSS_SUCCESS) {
std::printf("[DSSApiFileTest] dss_set_svr_path failed (svr_path=%s), skip business test.\n", svr_path);
return;
}
(void)dss_fremove(src_path);
(void)dss_fremove(dst_path);
int ret = dss_fcreate(src_path, 0);
if (ret != DSS_SUCCESS) {
std::printf("[DSSApiFileTest] dss_fcreate failed for %s, skip business test.\n", src_path);
return;
}
int handle = -1;
ret = dss_fopen(src_path, O_RDWR, &handle);
if (ret != DSS_SUCCESS) {
std::printf("[DSSApiFileTest] dss_fopen failed for %s, skip business test.\n", src_path);
(void)dss_fremove(src_path);
return;
}
const char *content = "COPY_TEST_CONTENT";
int content_len = static_cast<int>(std::strlen(content));
ret = dss_fwrite(handle, content, content_len);
ASSERT_EQ(DSS_SUCCESS, ret);
ret = dss_fclose(handle);
ASSERT_EQ(DSS_SUCCESS, ret);
ret = dss_fcopy(src_path, dst_path);
ASSERT_EQ(DSS_SUCCESS, ret);
dss_stat_t src_stat = {0};
dss_stat_t dst_stat = {0};
ret = dss_stat(src_path, &src_stat);
ASSERT_EQ(DSS_SUCCESS, ret);
ret = dss_stat(dst_path, &dst_stat);
ASSERT_EQ(DSS_SUCCESS, ret);
EXPECT_EQ(src_stat.type, dst_stat.type);
EXPECT_EQ(src_stat.size, dst_stat.size);
EXPECT_EQ(static_cast<unsigned long long>(content_len), dst_stat.size);
ret = dss_fremove(src_path);
ASSERT_EQ(DSS_SUCCESS, ret);
ret = dss_fremove(dst_path);
ASSERT_EQ(DSS_SUCCESS, ret);
}
TEST(DSSApiFileTest, OpenNonExistFileShouldFail)
{
const char *file_base = GetEnvOrNull("DSS_GTEST_FILE_PATH");
if (file_base == nullptr) {
std::printf("[DSSApiFileTest] DSS_GTEST_FILE_PATH not set, skip business test.\n");
return;
}
char svr_path[1024] = {0};
if (!BuildDssSvrPath(svr_path, sizeof(svr_path))) {
return;
}
char file_path[1024] = {0};
if (!BuildSubFilePath(file_base, "_nonexist", file_path, sizeof(file_path))) {
return;
}
if (dss_set_svr_path(svr_path) != DSS_SUCCESS) {
std::printf("[DSSApiFileTest] dss_set_svr_path failed (svr_path=%s), skip business test.\n", svr_path);
return;
}
(void)dss_fremove(file_path);
int handle = 12345;
int ret = dss_fopen(file_path, O_RDONLY, &handle);
EXPECT_NE(DSS_SUCCESS, ret);
EXPECT_EQ(-1, handle);
}