/** * @file tfsTest.cpp * @author slguan (slguan@taosdata.com) * @brief TFS module tests * @version 1.0 * @date 2022-01-20 * * @copyright Copyright (c) 2022 * */ #include #include "os.h" #include "tfs.h" class TfsTest : public ::testing::Test { protected: static void SetUpTestSuite() { root = "/tmp/tfsTest"; } static void TearDownTestSuite() {} public: void SetUp() override {} void TearDown() override {} static const char *root; }; const char *TfsTest::root; TEST_F(TfsTest, 01_Open_Close) { SDiskCfg dCfg = {0}; tstrncpy(dCfg.dir, root, TSDB_FILENAME_LEN); dCfg.level = 0; dCfg.primary = 1; taosRemoveDir(root); STfs *pTfs = tfsOpen(&dCfg, 1); ASSERT_EQ(pTfs, nullptr); taosMkDir(root); pTfs = tfsOpen(&dCfg, 1); ASSERT_NE(pTfs, nullptr); tfsUpdateSize(pTfs); SDiskSize size = tfsGetSize(pTfs); EXPECT_GT(size.avail, 0); EXPECT_GT(size.used, 0); EXPECT_GT(size.total, size.avail); EXPECT_GT(size.total, size.used); tfsClose(pTfs); } TEST_F(TfsTest, 02_AllocDisk) { int32_t code = 0; SDiskCfg dCfg = {0}; tstrncpy(dCfg.dir, root, TSDB_FILENAME_LEN); dCfg.level = 0; dCfg.primary = 1; taosRemoveDir(root); taosMkDir(root); STfs *pTfs = tfsOpen(&dCfg, 1); ASSERT_NE(pTfs, nullptr); SDiskID did; did.id = 0; did.level = 0; code = tfsAllocDisk(pTfs, 0, &did); EXPECT_EQ(code, 0); EXPECT_EQ(did.id, 0); EXPECT_EQ(did.level, 0); did.id = 1; did.level = 1; code = tfsAllocDisk(pTfs, 0, &did); EXPECT_EQ(code, 0); EXPECT_EQ(did.id, 0); EXPECT_EQ(did.level, 0); did.id = 1; did.level = 2; code = tfsAllocDisk(pTfs, 0, &did); EXPECT_EQ(code, 0); EXPECT_EQ(did.id, 0); EXPECT_EQ(did.level, 0); did.id = 1; did.level = 3; code = tfsAllocDisk(pTfs, 0, &did); EXPECT_EQ(code, 0); EXPECT_EQ(did.id, 0); EXPECT_EQ(did.level, 0); const char *primary = tfsGetPrimaryPath(pTfs); EXPECT_STREQ(primary, root); const char *path = tfsGetDiskPath(pTfs, did); EXPECT_STREQ(path, root); tfsClose(pTfs); } TEST_F(TfsTest, 03_Dir) { int32_t code = 0; SDiskCfg dCfg = {0}; tstrncpy(dCfg.dir, root, TSDB_FILENAME_LEN); dCfg.level = 0; dCfg.primary = 1; taosRemoveDir(root); taosMkDir(root); STfs *pTfs = tfsOpen(&dCfg, 1); ASSERT_NE(pTfs, nullptr); char p1[] = "p1"; char ap1[128] = {0}; snprintf(ap1, 128, "%s%s%s", root, TD_DIRSEP, p1); EXPECT_NE(taosDirExist(ap1), 0); EXPECT_EQ(tfsMkdir(pTfs, p1), 0); EXPECT_EQ(taosDirExist(ap1), 0); char p2[] = "p2"; char ap2[128] = {0}; snprintf(ap2, 128, "%s%s%s", root, TD_DIRSEP, p2); SDiskID did = {0}; EXPECT_NE(taosDirExist(ap2), 0); EXPECT_EQ(tfsMkdirAt(pTfs, p2, did), 0); EXPECT_EQ(taosDirExist(ap2), 0); char p3[] = "p3/p2/p1/p0"; char ap3[128] = {0}; snprintf(ap3, 128, "%s%s%s", root, TD_DIRSEP, p3); EXPECT_NE(taosDirExist(ap3), 0); EXPECT_NE(tfsMkdir(pTfs, p3), 0); EXPECT_NE(tfsMkdirAt(pTfs, p3, did), 0); EXPECT_EQ(tfsMkdirRecurAt(pTfs, p3, did), 0); EXPECT_EQ(taosDirExist(ap3), 0); EXPECT_EQ(tfsRmdir(pTfs, p3), 0); EXPECT_NE(taosDirExist(ap3), 0); char p45[] = "p5"; char p44[] = "p4"; char p4[] = "p4/p2/p1/p0"; char ap4[128] = {0}; snprintf(ap4, 128, "%s%s%s", root, TD_DIRSEP, p4); EXPECT_NE(taosDirExist(ap4), 0); EXPECT_EQ(tfsMkdirRecurAt(pTfs, p4, did), 0); EXPECT_EQ(taosDirExist(ap4), 0); EXPECT_EQ(tfsRename(pTfs, p44, p45), 0); EXPECT_EQ(tfsRmdir(pTfs, p4), 0); EXPECT_NE(taosDirExist(ap4), 0); tfsClose(pTfs); } TEST_F(TfsTest, 04_File) { int32_t code = 0; SDiskCfg dCfg = {0}; tstrncpy(dCfg.dir, root, TSDB_FILENAME_LEN); dCfg.level = 0; dCfg.primary = 1; taosRemoveDir(root); taosMkDir(root); STfs *pTfs = tfsOpen(&dCfg, 1); ASSERT_NE(pTfs, nullptr); STfsFile file0; STfsFile file1; STfsFile file2; STfsFile file3; STfsFile file4; SDiskID did0 = {0}; SDiskID did1 = {0}; SDiskID did2 = {0}; SDiskID did3 = {0}; SDiskID did4 = {0}; did3.id = 1; did4.level = 1; tfsInitFile(pTfs, &file0, did0, "fname"); tfsInitFile(pTfs, &file1, did1, "fname"); tfsInitFile(pTfs, &file2, did2, "fnamex"); tfsInitFile(pTfs, &file3, did3, "fname"); tfsInitFile(pTfs, &file4, did4, "fname"); EXPECT_TRUE(tfsIsSameFile(&file0, &file1)); EXPECT_FALSE(tfsIsSameFile(&file0, &file2)); EXPECT_FALSE(tfsIsSameFile(&file0, &file3)); EXPECT_FALSE(tfsIsSameFile(&file0, &file4)); { int32_t size = 1024; void *ret = malloc(size + sizeof(size_t)); *(size_t *)ret = size; void *buf = (void *)((char *)ret + sizeof(size_t)); file0.did.id = 0; file0.did.level = 0; int32_t len = tfsEncodeFile((void **)&buf, &file0); EXPECT_EQ(len, 8); STfsFile outfile = {0}; char *outbuf = (char *)tfsDecodeFile(pTfs, (void *)((char *)buf - len), &outfile); int32_t decodeLen = (outbuf - (char *)buf); EXPECT_EQ(outfile.did.id, 0); EXPECT_EQ(outfile.did.level, 0); EXPECT_STREQ(outfile.aname, file0.aname); EXPECT_STREQ(outfile.rname, "fname"); EXPECT_EQ(outfile.pTfs, pTfs); } { char n1[] = "t3/t1.json"; char n2[] = "t3/t2.json"; STfsFile f1 = {0}; STfsFile f2 = {0}; SDiskID did; did.id = 0; did.level = 0; tfsInitFile(pTfs, &f1, did, n1); tfsInitFile(pTfs, &f2, did, n2); EXPECT_EQ(tfsMkdir(pTfs, "t3"), 0); FILE *fp = fopen(f1.aname, "w"); ASSERT_NE(fp, nullptr); fwrite("12345678", 1, 5, fp); fclose(fp); char base[128] = {0}; tfsBasename(&f1, base); char dir[128] = {0}; tfsDirname(&f1, dir); EXPECT_STREQ(base, "t1.json"); char fulldir[128]; snprintf(fulldir, 128, "%s%s%s", root, TD_DIRSEP, "t3"); EXPECT_STREQ(dir, fulldir); EXPECT_GT(tfsCopyFile(&f1, &f2), 0); char af2[128] = {0}; snprintf(af2, 128, "%s%s%s", root, TD_DIRSEP, n2); EXPECT_EQ(taosDirExist(af2), 0); tfsRemoveFile(&f2); EXPECT_NE(taosDirExist(af2), 0); { STfsDir *pDir = tfsOpendir(pTfs, "t3"); const STfsFile *pf1 = tfsReaddir(pDir); EXPECT_NE(pf1, nullptr); EXPECT_EQ(pf1->did.id, 0); EXPECT_EQ(pf1->did.level, 0); EXPECT_EQ(pf1->pTfs, pTfs); const STfsFile *pf2 = tfsReaddir(pDir); EXPECT_EQ(pf2, nullptr); tfsClosedir(pDir); } EXPECT_GT(tfsCopyFile(&f1, &f2), 0); { STfsDir *pDir = tfsOpendir(pTfs, "t3"); const STfsFile *pf1 = tfsReaddir(pDir); EXPECT_NE(pf1, nullptr); EXPECT_EQ(pf1->did.id, 0); EXPECT_EQ(pf1->did.level, 0); EXPECT_EQ(pf1->pTfs, pTfs); const STfsFile *pf2 = tfsReaddir(pDir); EXPECT_EQ(pf2->did.id, 0); EXPECT_EQ(pf2->did.level, 0); EXPECT_EQ(pf2->pTfs, pTfs); const STfsFile *pf3 = tfsReaddir(pDir); EXPECT_EQ(pf3, nullptr); tfsClosedir(pDir); } } tfsClose(pTfs); } TEST_F(TfsTest, 05_MultiDisk) { int32_t code = 0; const char *root00 = "/tmp/tfsTest00"; const char *root01 = "/tmp/tfsTest01"; const char *root10 = "/tmp/tfsTest10"; const char *root11 = "/tmp/tfsTest11"; const char *root12 = "/tmp/tfsTest12"; const char *root20 = "/tmp/tfsTest20"; const char *root21 = "/tmp/tfsTest21"; const char *root22 = "/tmp/tfsTest22"; const char *root23 = "/tmp/tfsTest23"; SDiskCfg dCfg[9] = {0}; tstrncpy(dCfg[0].dir, root01, TSDB_FILENAME_LEN); dCfg[0].level = 0; dCfg[0].primary = 0; tstrncpy(dCfg[1].dir, root00, TSDB_FILENAME_LEN); dCfg[1].level = 0; dCfg[1].primary = 0; tstrncpy(dCfg[2].dir, root20, TSDB_FILENAME_LEN); dCfg[2].level = 2; dCfg[2].primary = 0; tstrncpy(dCfg[3].dir, root21, TSDB_FILENAME_LEN); dCfg[3].level = 2; dCfg[3].primary = 0; tstrncpy(dCfg[4].dir, root22, TSDB_FILENAME_LEN); dCfg[4].level = 2; dCfg[4].primary = 0; tstrncpy(dCfg[5].dir, root23, TSDB_FILENAME_LEN); dCfg[5].level = 2; dCfg[5].primary = 0; tstrncpy(dCfg[6].dir, root10, TSDB_FILENAME_LEN); dCfg[6].level = 1; dCfg[6].primary = 0; tstrncpy(dCfg[7].dir, root11, TSDB_FILENAME_LEN); dCfg[7].level = 1; dCfg[7].primary = 0; tstrncpy(dCfg[8].dir, root12, TSDB_FILENAME_LEN); dCfg[8].level = 1; dCfg[8].primary = 0; taosRemoveDir(root00); taosRemoveDir(root01); taosRemoveDir(root10); taosRemoveDir(root11); taosRemoveDir(root12); taosRemoveDir(root20); taosRemoveDir(root21); taosRemoveDir(root22); taosRemoveDir(root23); taosMkDir(root00); taosMkDir(root01); taosMkDir(root10); taosMkDir(root11); taosMkDir(root12); taosMkDir(root20); taosMkDir(root21); taosMkDir(root22); taosMkDir(root23); STfs *pTfs = tfsOpen(dCfg, 9); ASSERT_EQ(pTfs, nullptr); dCfg[0].primary = 1; dCfg[1].primary = 1; pTfs = tfsOpen(dCfg, 9); ASSERT_EQ(pTfs, nullptr); dCfg[0].primary = 0; dCfg[1].primary = 1; pTfs = tfsOpen(dCfg, 9); ASSERT_NE(pTfs, nullptr); tfsUpdateSize(pTfs); SDiskSize size = tfsGetSize(pTfs); EXPECT_GT(size.avail, 0); EXPECT_GT(size.used, 0); EXPECT_GT(size.total, size.avail); EXPECT_GT(size.total, size.used); //------------- AllocDisk -----------------// { const char *path = NULL; SDiskID did; did.id = 0; did.level = 0; code = tfsAllocDisk(pTfs, 0, &did); EXPECT_EQ(code, 0); EXPECT_EQ(did.id, 0); EXPECT_EQ(did.level, 0); path = tfsGetDiskPath(pTfs, did); EXPECT_STREQ(path, root00); code = tfsAllocDisk(pTfs, 0, &did); EXPECT_EQ(code, 0); EXPECT_EQ(did.id, 1); EXPECT_EQ(did.level, 0); path = tfsGetDiskPath(pTfs, did); EXPECT_STREQ(path, root01); code = tfsAllocDisk(pTfs, 0, &did); EXPECT_EQ(code, 0); EXPECT_EQ(did.id, 0); EXPECT_EQ(did.level, 0); path = tfsGetDiskPath(pTfs, did); EXPECT_STREQ(path, root00); code = tfsAllocDisk(pTfs, 0, &did); EXPECT_EQ(code, 0); EXPECT_EQ(did.id, 1); EXPECT_EQ(did.level, 0); path = tfsGetDiskPath(pTfs, did); EXPECT_STREQ(path, root01); code = tfsAllocDisk(pTfs, 0, &did); EXPECT_EQ(code, 0); EXPECT_EQ(did.id, 0); EXPECT_EQ(did.level, 0); path = tfsGetDiskPath(pTfs, did); EXPECT_STREQ(path, root00); code = tfsAllocDisk(pTfs, 0, &did); EXPECT_EQ(code, 0); EXPECT_EQ(did.id, 1); EXPECT_EQ(did.level, 0); path = tfsGetDiskPath(pTfs, did); EXPECT_STREQ(path, root01); code = tfsAllocDisk(pTfs, 1, &did); EXPECT_EQ(code, 0); EXPECT_EQ(did.id, 0); EXPECT_EQ(did.level, 1); path = tfsGetDiskPath(pTfs, did); EXPECT_STREQ(path, root10); code = tfsAllocDisk(pTfs, 1, &did); EXPECT_EQ(code, 0); EXPECT_EQ(did.id, 1); EXPECT_EQ(did.level, 1); path = tfsGetDiskPath(pTfs, did); EXPECT_STREQ(path, root11); code = tfsAllocDisk(pTfs, 1, &did); EXPECT_EQ(code, 0); EXPECT_EQ(did.id, 2); EXPECT_EQ(did.level, 1); path = tfsGetDiskPath(pTfs, did); EXPECT_STREQ(path, root12); code = tfsAllocDisk(pTfs, 1, &did); EXPECT_EQ(code, 0); EXPECT_EQ(did.id, 0); EXPECT_EQ(did.level, 1); path = tfsGetDiskPath(pTfs, did); EXPECT_STREQ(path, root10); code = tfsAllocDisk(pTfs, 2, &did); EXPECT_EQ(code, 0); EXPECT_EQ(did.id, 0); EXPECT_EQ(did.level, 2); path = tfsGetDiskPath(pTfs, did); EXPECT_STREQ(path, root20); code = tfsAllocDisk(pTfs, 2, &did); EXPECT_EQ(code, 0); EXPECT_EQ(did.id, 1); EXPECT_EQ(did.level, 2); path = tfsGetDiskPath(pTfs, did); EXPECT_STREQ(path, root21); code = tfsAllocDisk(pTfs, 2, &did); EXPECT_EQ(code, 0); EXPECT_EQ(did.id, 2); EXPECT_EQ(did.level, 2); path = tfsGetDiskPath(pTfs, did); EXPECT_STREQ(path, root22); code = tfsAllocDisk(pTfs, 2, &did); EXPECT_EQ(code, 0); EXPECT_EQ(did.id, 3); EXPECT_EQ(did.level, 2); path = tfsGetDiskPath(pTfs, did); EXPECT_STREQ(path, root23); code = tfsAllocDisk(pTfs, 2, &did); EXPECT_EQ(code, 0); EXPECT_EQ(did.id, 0); EXPECT_EQ(did.level, 2); path = tfsGetDiskPath(pTfs, did); EXPECT_STREQ(path, root20); code = tfsAllocDisk(pTfs, 3, &did); EXPECT_EQ(code, 0); EXPECT_EQ(did.id, 1); EXPECT_EQ(did.level, 2); path = tfsGetDiskPath(pTfs, did); EXPECT_STREQ(path, root21); code = tfsAllocDisk(pTfs, 4, &did); EXPECT_EQ(code, 0); EXPECT_EQ(did.id, 2); EXPECT_EQ(did.level, 2); path = tfsGetDiskPath(pTfs, did); EXPECT_STREQ(path, root22); const char *primary = tfsGetPrimaryPath(pTfs); EXPECT_STREQ(primary, root00); } //------------- Dir -----------------// { char p1[] = "p1"; char ap00[128] = {0}; snprintf(ap00, 128, "%s%s%s", root00, TD_DIRSEP, p1); char ap01[128] = {0}; snprintf(ap01, 128, "%s%s%s", root01, TD_DIRSEP, p1); char ap10[128] = {0}; snprintf(ap10, 128, "%s%s%s", root10, TD_DIRSEP, p1); char ap11[128] = {0}; snprintf(ap11, 128, "%s%s%s", root11, TD_DIRSEP, p1); char ap12[128] = {0}; snprintf(ap12, 128, "%s%s%s", root12, TD_DIRSEP, p1); char ap20[128] = {0}; snprintf(ap20, 128, "%s%s%s", root20, TD_DIRSEP, p1); char ap21[128] = {0}; snprintf(ap21, 128, "%s%s%s", root21, TD_DIRSEP, p1); char ap22[128] = {0}; snprintf(ap22, 128, "%s%s%s", root22, TD_DIRSEP, p1); char ap23[128] = {0}; snprintf(ap23, 128, "%s%s%s", root23, TD_DIRSEP, p1); EXPECT_NE(taosDirExist(ap00), 0); EXPECT_NE(taosDirExist(ap01), 0); EXPECT_NE(taosDirExist(ap10), 0); EXPECT_NE(taosDirExist(ap11), 0); EXPECT_NE(taosDirExist(ap12), 0); EXPECT_NE(taosDirExist(ap20), 0); EXPECT_NE(taosDirExist(ap21), 0); EXPECT_NE(taosDirExist(ap22), 0); EXPECT_NE(taosDirExist(ap23), 0); EXPECT_EQ(tfsMkdir(pTfs, p1), 0); EXPECT_EQ(taosDirExist(ap00), 0); EXPECT_EQ(taosDirExist(ap01), 0); EXPECT_EQ(taosDirExist(ap10), 0); EXPECT_EQ(taosDirExist(ap11), 0); EXPECT_EQ(taosDirExist(ap12), 0); EXPECT_EQ(taosDirExist(ap20), 0); EXPECT_EQ(taosDirExist(ap21), 0); EXPECT_EQ(taosDirExist(ap22), 0); EXPECT_EQ(taosDirExist(ap23), 0); EXPECT_EQ(tfsRmdir(pTfs, p1), 0); EXPECT_NE(taosDirExist(ap00), 0); EXPECT_NE(taosDirExist(ap01), 0); EXPECT_NE(taosDirExist(ap10), 0); EXPECT_NE(taosDirExist(ap11), 0); EXPECT_NE(taosDirExist(ap12), 0); EXPECT_NE(taosDirExist(ap20), 0); EXPECT_NE(taosDirExist(ap21), 0); EXPECT_NE(taosDirExist(ap22), 0); EXPECT_NE(taosDirExist(ap23), 0); char p2[] = "p2"; char _ap21[128] = {0}; snprintf(_ap21, 128, "%s%s%s", root21, TD_DIRSEP, p2); SDiskID did = {0}; did.level = 2; did.id = 1; EXPECT_NE(taosDirExist(_ap21), 0); EXPECT_EQ(tfsMkdirAt(pTfs, p2, did), 0); EXPECT_EQ(taosDirExist(_ap21), 0); char p3[] = "p3/p2/p1/p0"; char _ap12[128] = {0}; snprintf(_ap12, 128, "%s%s%s", root12, TD_DIRSEP, p3); did.level = 1; did.id = 2; EXPECT_NE(taosDirExist(_ap12), 0); EXPECT_NE(tfsMkdir(pTfs, p3), 0); EXPECT_NE(tfsMkdirAt(pTfs, p3, did), 0); EXPECT_EQ(tfsMkdirRecurAt(pTfs, p3, did), 0); EXPECT_EQ(taosDirExist(_ap12), 0); EXPECT_EQ(tfsRmdir(pTfs, p3), 0); EXPECT_NE(taosDirExist(_ap12), 0); char p45[] = "p5"; char p44[] = "p4"; char p4[] = "p4/p2/p1/p0"; char _ap22[128] = {0}; snprintf(_ap22, 128, "%s%s%s", root22, TD_DIRSEP, p4); did.level = 2; did.id = 2; EXPECT_NE(taosDirExist(_ap22), 0); EXPECT_EQ(tfsMkdirRecurAt(pTfs, p4, did), 0); EXPECT_EQ(taosDirExist(_ap22), 0); EXPECT_EQ(tfsRename(pTfs, p44, p45), 0); EXPECT_EQ(tfsRmdir(pTfs, p4), 0); EXPECT_NE(taosDirExist(_ap22), 0); } //------------- File -----------------// { STfsFile file0; STfsFile file1; STfsFile file2; STfsFile file3; STfsFile file4; SDiskID did0 = {0}; SDiskID did1 = {0}; SDiskID did2 = {0}; SDiskID did3 = {0}; SDiskID did4 = {0}; did3.id = 1; did4.level = 1; tfsInitFile(pTfs, &file0, did0, "fname"); tfsInitFile(pTfs, &file1, did1, "fname"); tfsInitFile(pTfs, &file2, did2, "fnamex"); tfsInitFile(pTfs, &file3, did3, "fname"); tfsInitFile(pTfs, &file4, did4, "fname"); EXPECT_TRUE(tfsIsSameFile(&file0, &file1)); EXPECT_FALSE(tfsIsSameFile(&file0, &file2)); EXPECT_FALSE(tfsIsSameFile(&file0, &file3)); EXPECT_FALSE(tfsIsSameFile(&file0, &file4)); { char n1[] = "t3/t1.json"; char n2[] = "t3/t2.json"; STfsFile f1 = {0}; STfsFile f2 = {0}; SDiskID did; did1.level = 1; did1.id = 2; did2.level = 2; did2.id = 3; tfsInitFile(pTfs, &f1, did1, n1); tfsInitFile(pTfs, &f2, did2, n2); EXPECT_EQ(tfsMkdir(pTfs, "t3"), 0); FILE *fp = fopen(f1.aname, "w"); ASSERT_NE(fp, nullptr); fwrite("12345678", 1, 5, fp); fclose(fp); char base[128] = {0}; tfsBasename(&f1, base); char dir[128] = {0}; tfsDirname(&f1, dir); EXPECT_STREQ(base, "t1.json"); char fulldir[128]; snprintf(fulldir, 128, "%s%s%s", root12, TD_DIRSEP, "t3"); EXPECT_STREQ(dir, fulldir); EXPECT_GT(tfsCopyFile(&f1, &f2), 0); char af2[128] = {0}; snprintf(af2, 128, "%s%s%s", root23, TD_DIRSEP, n2); EXPECT_EQ(taosDirExist(af2), 0); tfsRemoveFile(&f2); { STfsDir *pDir = tfsOpendir(pTfs, "t3"); const STfsFile *pf1 = tfsReaddir(pDir); EXPECT_NE(pf1, nullptr); EXPECT_EQ(pf1->did.level, 1); EXPECT_EQ(pf1->did.id, 2); EXPECT_EQ(pf1->pTfs, pTfs); const STfsFile *pf2 = tfsReaddir(pDir); EXPECT_EQ(pf2, nullptr); tfsClosedir(pDir); } EXPECT_NE(taosDirExist(af2), 0); EXPECT_GT(tfsCopyFile(&f1, &f2), 0); { STfsDir *pDir = tfsOpendir(pTfs, "t3"); const STfsFile *pf1 = tfsReaddir(pDir); EXPECT_NE(pf1, nullptr); EXPECT_GT(pf1->did.level, 0); EXPECT_GT(pf1->did.id, 0); EXPECT_EQ(pf1->pTfs, pTfs); const STfsFile *pf2 = tfsReaddir(pDir); EXPECT_NE(pf1, nullptr); EXPECT_GT(pf1->did.level, 0); EXPECT_GT(pf1->did.id, 0); EXPECT_EQ(pf1->pTfs, pTfs); const STfsFile *pf3 = tfsReaddir(pDir); EXPECT_EQ(pf3, nullptr); tfsClosedir(pDir); } } } tfsClose(pTfs); }