reform test_layer2_API with googletest framwork and revise mkdir & mknod return type
This commit is contained in:
parent
6f5bb3bdcc
commit
60678711d2
@ -18,8 +18,8 @@ class FilesOperation {
|
|||||||
void unlink_inode(u_int64_t inode_number);
|
void unlink_inode(u_int64_t inode_number);
|
||||||
u_int64_t disk_namei(const char* path);
|
u_int64_t disk_namei(const char* path);
|
||||||
u_int64_t namei(const char* path);
|
u_int64_t namei(const char* path);
|
||||||
u_int64_t fischl_mkdir(const char*, mode_t);
|
int fischl_mkdir(const char*, mode_t);
|
||||||
u_int64_t fischl_mknod(const char*, mode_t);
|
int fischl_mknod(const char*, mode_t);
|
||||||
//int fischl_readdir(const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *, enum fuse_readdir_flags);
|
//int fischl_readdir(const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *, enum fuse_readdir_flags);
|
||||||
int fischl_unlink (const char *);
|
int fischl_unlink (const char *);
|
||||||
//int fischl_open (const char *, struct fuse_file_info *);
|
//int fischl_open (const char *, struct fuse_file_info *);
|
||||||
|
@ -111,7 +111,7 @@ void FilesOperation::create_dot_dotdot(INode* inode, u_int64_t parent_inode_numb
|
|||||||
void FilesOperation::initialize_rootinode() {
|
void FilesOperation::initialize_rootinode() {
|
||||||
// this method must be called explicitly right after initializion
|
// this method must be called explicitly right after initializion
|
||||||
u_int64_t root_inode_number = inop.inode_allocate(disk);
|
u_int64_t root_inode_number = inop.inode_allocate(disk);
|
||||||
printf("Info: root inode number: %llu\n", root_inode_number);
|
// printf("Info: root inode number: %llu\n", root_inode_number);
|
||||||
INode *root_inode = new_inode(root_inode_number, S_IFDIR);
|
INode *root_inode = new_inode(root_inode_number, S_IFDIR);
|
||||||
create_dot_dotdot(root_inode, root_inode_number);
|
create_dot_dotdot(root_inode, root_inode_number);
|
||||||
root_node = fischl_init_entry(root_inode_number, "/", root_inode);
|
root_node = fischl_init_entry(root_inode_number, "/", root_inode);
|
||||||
@ -142,7 +142,7 @@ INode* FilesOperation::create_new_inode(u_int64_t parent_inode_number, const cha
|
|||||||
INode inode;
|
INode inode;
|
||||||
inode.inode_construct(parent_inode_number, disk);
|
inode.inode_construct(parent_inode_number, disk);
|
||||||
if ((inode.permissions & S_IFMT) != S_IFDIR) {
|
if ((inode.permissions & S_IFMT) != S_IFDIR) {
|
||||||
printf("Parent Inode is not a directory\n");
|
fprintf(stderr,"[%s ,%d] please create under directory\n",__func__,__LINE__);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +154,11 @@ INode* FilesOperation::create_new_inode(u_int64_t parent_inode_number, const cha
|
|||||||
for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){
|
for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){
|
||||||
ent.deserialize(r_buffer+i);
|
ent.deserialize(r_buffer+i);
|
||||||
if (strcmp(ent.file_name, name)==0) {
|
if (strcmp(ent.file_name, name)==0) {
|
||||||
printf("Already exists file or directory with name %s, cannot not create\n", name);
|
if((mode & S_IFMT) == S_IFDIR){
|
||||||
|
fprintf(stderr,"[%s ,%d] %s/ already exists\n",__func__,__LINE__, name);
|
||||||
|
}else{
|
||||||
|
fprintf(stderr,"[%s ,%d] %s already exists\n",__func__,__LINE__, name);
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -255,7 +259,7 @@ u_int64_t FilesOperation::namei(const char* path) {
|
|||||||
else return -1;
|
else return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
u_int64_t FilesOperation::fischl_mkdir(const char* path, mode_t mode) {
|
int FilesOperation::fischl_mkdir(const char* path, mode_t mode) {
|
||||||
//check path
|
//check path
|
||||||
char *pathdup = strdup(path);
|
char *pathdup = strdup(path);
|
||||||
char *lastSlash = strrchr(pathdup, '/');
|
char *lastSlash = strrchr(pathdup, '/');
|
||||||
@ -265,44 +269,41 @@ u_int64_t FilesOperation::fischl_mkdir(const char* path, mode_t mode) {
|
|||||||
|
|
||||||
FileNode *parent_filenode = strlen(ParentPath)? fischl_find_entry(root_node, ParentPath): root_node->self_info;
|
FileNode *parent_filenode = strlen(ParentPath)? fischl_find_entry(root_node, ParentPath): root_node->self_info;
|
||||||
if (parent_filenode == NULL) {
|
if (parent_filenode == NULL) {
|
||||||
printf("parent %s not found by fischl_find_entry\n", ParentPath);
|
fprintf(stderr,"[%s ,%d] ParentPath:{%s} not found\n",__func__,__LINE__, ParentPath);
|
||||||
delete pathdup;
|
delete pathdup;
|
||||||
return -1;
|
return -ENOENT;//parentpath directory does not exist
|
||||||
}
|
}
|
||||||
u_int64_t parent_inode_number = parent_filenode->inode_number;
|
u_int64_t parent_inode_number = parent_filenode->inode_number;
|
||||||
//make new inode
|
//make new inode
|
||||||
INode* ret = create_new_inode(parent_inode_number, newDirname, mode|S_IFDIR);//specify S_IFDIR as directory
|
INode* ret = create_new_inode(parent_inode_number, newDirname, mode|S_IFDIR);//specify S_IFDIR as directory
|
||||||
if (ret == NULL) return -1;
|
if (ret == NULL) return -1;//ENOSPC but create_new_inode handle ENAMETOOLONG EEXIST
|
||||||
fischl_add_entry(parent_filenode->subdirectory, ret->block_number, newDirname, ret);
|
fischl_add_entry(parent_filenode->subdirectory, ret->block_number, newDirname, ret);
|
||||||
delete pathdup;
|
delete pathdup;
|
||||||
return ret->block_number;
|
return 0;//SUCCESS
|
||||||
//after new_inode(mkfile), go to fischl_add_entry record
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u_int64_t FilesOperation::fischl_mknod(const char* path, mode_t mode) {
|
int FilesOperation::fischl_mknod(const char* path, mode_t mode) {
|
||||||
//check path
|
//check path
|
||||||
char *pathdup = strdup(path);
|
char *pathdup = strdup(path);
|
||||||
char *lastSlash = strrchr(pathdup, '/');
|
char *lastSlash = strrchr(pathdup, '/');
|
||||||
*lastSlash = '\0'; // Split the string into parent path and new directory name; <parent path>\0<direcotry name>
|
*lastSlash = '\0'; // Split the string into parent path and new directory name; <parent path>\0<direcotry name>
|
||||||
char *newFilename = lastSlash+1; //\0<direcotry name>, get from <direcotry name>
|
char *newFilename = lastSlash+1; //\0<direcotry name>, get from <direcotry name>
|
||||||
char *ParentPath = pathdup;//pathdup are separated by pathdup, so it take <parent path> only
|
char *ParentPath = pathdup;//pathdup are separated by pathdup, so it take <parent path> only
|
||||||
printf("mknod ParentPath:%s, strlen=%d\n", ParentPath, strlen(ParentPath));
|
// fprintf(stderr,"[%s ,%d] ParentPath:%s, strlen=%d\n",__func__,__LINE__, ParentPath, strlen(ParentPath));
|
||||||
FileNode *parent_filenode = strlen(ParentPath)? fischl_find_entry(root_node, ParentPath): root_node->self_info;
|
FileNode *parent_filenode = strlen(ParentPath)? fischl_find_entry(root_node, ParentPath): root_node->self_info;
|
||||||
if (parent_filenode == NULL) {
|
if (parent_filenode == NULL) {
|
||||||
printf("parent %s not found by fischl_find_entry\n", ParentPath);
|
fprintf(stderr,"[%s ,%d] ParentPath:{%s} not found\n",__func__,__LINE__, ParentPath);
|
||||||
delete pathdup;
|
delete pathdup;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
u_int64_t parent_inode_number = parent_filenode->inode_number;
|
u_int64_t parent_inode_number = parent_filenode->inode_number;
|
||||||
//make new inode
|
//make new inode
|
||||||
INode* ret = create_new_inode(parent_inode_number, newFilename, mode);
|
INode* ret = create_new_inode(parent_inode_number, newFilename, mode);
|
||||||
if (ret == NULL) return -1;
|
if (ret == NULL) return -1;//ENOSPC but create_new_inode handle ENAMETOOLONG EEXIST
|
||||||
//make new node
|
//make new node
|
||||||
fischl_add_entry(parent_filenode->subdirectory, ret->block_number, newFilename, ret);
|
fischl_add_entry(parent_filenode->subdirectory, ret->block_number, newFilename, ret);
|
||||||
delete pathdup;
|
delete pathdup;
|
||||||
return ret->block_number;
|
return 0;//SUCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilesOperation::unlink_inode(u_int64_t inode_number) {
|
void FilesOperation::unlink_inode(u_int64_t inode_number) {
|
||||||
|
@ -16,7 +16,7 @@ add_executable(${TARGET_LAYER1_API}
|
|||||||
add_executable(${TARGET_LAYER2_API}
|
add_executable(${TARGET_LAYER2_API}
|
||||||
../lib/direntry.cpp
|
../lib/direntry.cpp
|
||||||
../lib/files.cpp
|
../lib/files.cpp
|
||||||
layer2_API.cpp
|
layer2_API_dir.cpp
|
||||||
)
|
)
|
||||||
add_executable(${TARGET_DIR_API}
|
add_executable(${TARGET_DIR_API}
|
||||||
../lib/direntry.cpp
|
../lib/direntry.cpp
|
||||||
@ -26,6 +26,7 @@ add_executable(${TARGET_DIR_API}
|
|||||||
# Link Google Test to your test executables
|
# Link Google Test to your test executables
|
||||||
target_link_libraries(${TARGET_LAYER0} gtest gtest_main)
|
target_link_libraries(${TARGET_LAYER0} gtest gtest_main)
|
||||||
target_link_libraries(${TARGET_LAYER1_API} gtest gtest_main)
|
target_link_libraries(${TARGET_LAYER1_API} gtest gtest_main)
|
||||||
|
target_link_libraries(${TARGET_LAYER2_API} gtest gtest_main)
|
||||||
target_link_libraries(${TARGET_DIR_API} gtest gtest_main)
|
target_link_libraries(${TARGET_DIR_API} gtest gtest_main)
|
||||||
|
|
||||||
# add test to activate ctest -VV
|
# add test to activate ctest -VV
|
||||||
|
320
test/layer2_API_dir.cpp
Normal file
320
test/layer2_API_dir.cpp
Normal file
@ -0,0 +1,320 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include "files.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct file_test{
|
||||||
|
const char* name;
|
||||||
|
file_test* next;//use linked-list to know the file at the same level directory
|
||||||
|
}file_test;
|
||||||
|
typedef struct dir_test{
|
||||||
|
const char* name;
|
||||||
|
file_test* inFile;
|
||||||
|
dir_test* subdir;
|
||||||
|
dir_test* next;//use linked-list to know the other dir at the same parent dir.
|
||||||
|
}dir_test;
|
||||||
|
|
||||||
|
void setupTestDirectory(dir_test** root);
|
||||||
|
void freeDirHierarchy(dir_test* dir);
|
||||||
|
void traverseDirHierarchy(const dir_test* dir, int depth);
|
||||||
|
|
||||||
|
//global can be taken
|
||||||
|
const char* d;
|
||||||
|
TreeNode *root;
|
||||||
|
std::string target_filepath;
|
||||||
|
dir_test* mock_root = nullptr;
|
||||||
|
|
||||||
|
int total_dir_num = 0;
|
||||||
|
int total_file_num = 0;
|
||||||
|
int total_free_dir = 0;
|
||||||
|
int total_free_file = 0;
|
||||||
|
|
||||||
|
TEST(FileOperationTest, MkdirnodTest) {
|
||||||
|
RawDisk *H = new RawDisk(d);
|
||||||
|
|
||||||
|
FilesOperation fsop(*H);
|
||||||
|
fsop.initialize_rootinode();
|
||||||
|
|
||||||
|
mode_t mode;//set mode
|
||||||
|
mode = S_IRWXU | S_IRWXG | S_IRWXO;//future should test permission
|
||||||
|
//S_IRWXU(S_IRUSR | S_IWUSR | S_IXUSR) (owner), S_IRWXG(S_IRGRP | S_IWGRP | S_IXGRP) (group), S_IRWXO(S_IROTH | S_IWOTH | S_IXOTH)
|
||||||
|
EXPECT_EQ(fsop.fischl_mknod("/test", mode), 0); // mode here is not used yet
|
||||||
|
EXPECT_EQ(fsop.fischl_mkdir("/foo", mode), 0);
|
||||||
|
EXPECT_EQ(fsop.fischl_mkdir("/foo/bar", mode),0);
|
||||||
|
EXPECT_EQ(fsop.fischl_mknod("/foo/bar/baz", mode), 0);
|
||||||
|
// the following three testcases will fail
|
||||||
|
EXPECT_TRUE(fsop.fischl_mkdir("foo/bar", mode) < 0);
|
||||||
|
EXPECT_TRUE(fsop.fischl_mkdir("/doesnt_exist/bar", mode) < 0);
|
||||||
|
EXPECT_TRUE(fsop.fischl_mkdir("/test/bar", mode) < 0);
|
||||||
|
EXPECT_TRUE(fsop.fischl_mkdir("/test", mode) < 0);
|
||||||
|
EXPECT_TRUE(fsop.fischl_mkdir("/foo/bar", mode) < 0);
|
||||||
|
EXPECT_TRUE(fsop.fischl_mkdir("/foo/bar/..", mode) < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TEST(FileOperationTest, WriteTest) {
|
||||||
|
// // write to files (TODO: fischl_write)
|
||||||
|
// // read and write to indirect datablocks are not supported yet
|
||||||
|
// printf("=== Part 2: write to files ===\n");
|
||||||
|
// char buffer[IO_BLOCK_SIZE] = {0};
|
||||||
|
// INode inode;
|
||||||
|
// inode.inode_construct(file1, *H);
|
||||||
|
// buffer[0] = '1';
|
||||||
|
// fsop.write_datablock(inode, 0, buffer);
|
||||||
|
// inode.inode_save(*H);
|
||||||
|
// inode.inode_construct(file4, *H);
|
||||||
|
// buffer[0] = '4';
|
||||||
|
// fsop.write_datablock(inode, 3, buffer);
|
||||||
|
// buffer[0] = '5';
|
||||||
|
// fsop.write_datablock(inode, 101, buffer);
|
||||||
|
// inode.inode_save(*H);
|
||||||
|
// // TODO: guard against overwriting directory datablocks
|
||||||
|
// }
|
||||||
|
|
||||||
|
// TEST(FileOperationTest, RamTest) {
|
||||||
|
// // retrieve inode-number by path
|
||||||
|
// u_int64_t file_test = fsop.namei("/test");
|
||||||
|
// printf("inode number for \"/test\" is %llu\n", file_test);
|
||||||
|
// assert(file_test == file1);
|
||||||
|
// u_int64_t file_baz = fsop.namei("/foo/bar/baz");
|
||||||
|
// printf("inode number for \"/foo/bar/baz\" is %llu\n", file_baz);
|
||||||
|
// assert(file_baz == file4);
|
||||||
|
// u_int64_t file_foo = fsop.namei("/foo/bar/..");
|
||||||
|
// printf("inode number for \"/foo/bar/..\" is %llu\n", file_foo);
|
||||||
|
// assert(file_foo == file2);
|
||||||
|
// u_int64_t file_bar = fsop.namei("/foo/bar/.");
|
||||||
|
// printf("inode number for \"/foo/bar/.\" is %llu\n", file_bar);
|
||||||
|
// assert(file_bar == file3);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// TEST(FileOperationTest, DiskTest) {
|
||||||
|
// // retrieve inode-number by path
|
||||||
|
// u_int64_t file_test = fsop.namei("/test");
|
||||||
|
// printf("inode number for \"/test\" is %llu\n", file_test);
|
||||||
|
// assert(file_test == file1);
|
||||||
|
// u_int64_t file_baz = fsop.namei("/foo/bar/baz");
|
||||||
|
// printf("inode number for \"/foo/bar/baz\" is %llu\n", file_baz);
|
||||||
|
// assert(file_baz == file4);
|
||||||
|
// u_int64_t file_foo = fsop.namei("/foo/bar/..");
|
||||||
|
// printf("inode number for \"/foo/bar/..\" is %llu\n", file_foo);
|
||||||
|
// assert(file_foo == file2);
|
||||||
|
// u_int64_t file_bar = fsop.namei("/foo/bar/.");
|
||||||
|
// printf("inode number for \"/foo/bar/.\" is %llu\n", file_bar);
|
||||||
|
// assert(file_bar == file3);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// TEST(FileOperationTest, ReadTest) {
|
||||||
|
// // read files (TODO: fischl_read)
|
||||||
|
// char read_buffer[IO_BLOCK_SIZE] = {0};
|
||||||
|
// INode inode_read;
|
||||||
|
// inode_read.inode_construct(file_test, *H);
|
||||||
|
// fsop.read_datablock(inode_read, 0, read_buffer);
|
||||||
|
// assert(read_buffer[0] == '1');
|
||||||
|
// inode_read.inode_construct(file_baz, *H);
|
||||||
|
// fsop.read_datablock(inode_read, 3, read_buffer);
|
||||||
|
// assert(read_buffer[0] == '4');
|
||||||
|
// fsop.read_datablock(inode_read, 101, read_buffer);
|
||||||
|
// assert(read_buffer[0] == '5');
|
||||||
|
// }
|
||||||
|
// TEST(FileOperationTest, PressureTest) {
|
||||||
|
// printf("=== Part 5: pressure test create files ===\n");
|
||||||
|
// u_int64_t file_pressure = fsop.fischl_mkdir("/pressure", 0);
|
||||||
|
// u_int64_t inode_numbers[700];
|
||||||
|
// std::string prefix = "/pressure/No_";
|
||||||
|
// for(int i=0;i<700;i++){
|
||||||
|
// inode_numbers[i] = fsop.fischl_mkdir((prefix+std::to_string(i)).c_str(), 0);
|
||||||
|
// }
|
||||||
|
// for(int i=0;i<700;i++){
|
||||||
|
// u_int64_t inode_number = fsop.namei((prefix+std::to_string(i)).c_str());
|
||||||
|
// assert(inode_number == inode_numbers[i]);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// TEST(FileOperationTest, UnlinkTest) {
|
||||||
|
// printf("=== Part 6: unlink test ===\n");
|
||||||
|
// fsop.printDirectory(file_pressure);
|
||||||
|
// for(int i=0;i<700;i+=2){
|
||||||
|
// assert(!fsop.fischl_unlink((prefix+std::to_string(i)).c_str()));
|
||||||
|
// }
|
||||||
|
// for(int i=0;i<4;i+=2){
|
||||||
|
// assert(fsop.namei((prefix+std::to_string(i)).c_str())==(u_int64_t)(-1));
|
||||||
|
// }
|
||||||
|
// for(int i=1;i<700;i+=2){
|
||||||
|
// u_int64_t inode_number = fsop.namei((prefix+std::to_string(i)).c_str());
|
||||||
|
// assert(inode_number == inode_numbers[i]);
|
||||||
|
// }
|
||||||
|
// fsop.printDirectory(file_pressure);
|
||||||
|
// std::string newprefix = "/pressure/New";
|
||||||
|
// for(int i=0;i<700;i+=2){
|
||||||
|
// inode_numbers[i] = fsop.fischl_mkdir((newprefix+std::to_string(i)).c_str(), 0);
|
||||||
|
// }
|
||||||
|
// for(int i=0;i<700;i+=2){
|
||||||
|
// u_int64_t inode_number = fsop.namei((newprefix+std::to_string(i)).c_str());
|
||||||
|
// assert(inode_number == inode_numbers[i]);
|
||||||
|
// }
|
||||||
|
// fsop.printDirectory(file_pressure);
|
||||||
|
|
||||||
|
// // long filename test
|
||||||
|
// std::string longfilename = std::string(255,'A');
|
||||||
|
// u_int64_t filelong = fsop.fischl_mknod((std::string("/")+longfilename).c_str(),0);
|
||||||
|
// printf("/AAA...AAA is inode %llu, it is a file\n", filelong);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
srand(time(NULL)); // Seed the random number generator
|
||||||
|
d = (argc < 2) ? "/dev/vdc" : argv[1];
|
||||||
|
|
||||||
|
setupTestDirectory(&mock_root);
|
||||||
|
|
||||||
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
int result = RUN_ALL_TESTS();
|
||||||
|
|
||||||
|
total_dir_num = 0;
|
||||||
|
total_file_num = 0;
|
||||||
|
|
||||||
|
traverseDirHierarchy(mock_root, 0);//mock_root
|
||||||
|
printf("Traverse Total: Dir %d, File %d\n",total_dir_num, total_file_num);
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
freeDirHierarchy(mock_root);//mock_root
|
||||||
|
printf("Free Total: Dir %d, File %d\n",total_free_dir, total_free_file);
|
||||||
|
freeTree(root);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* generateRandomName(size_t length) {
|
||||||
|
const std::string chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||||
|
std::string randomString;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < length; ++i) {
|
||||||
|
randomString += chars[rand() % chars.size()];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate memory and copy the string
|
||||||
|
char* name = new char[randomString.length() + 1];
|
||||||
|
strcpy(name, randomString.c_str());
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recursive function to create directory hierarchy
|
||||||
|
dir_test* createDirHierarchy(int level, int maxLevel) {
|
||||||
|
if (level > maxLevel) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
dir_test* head = nullptr;
|
||||||
|
dir_test* current = nullptr;
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
dir_test* newDir = new dir_test;
|
||||||
|
newDir->name = generateRandomName(6); // Generate a random name for the directory
|
||||||
|
newDir->inFile = nullptr; // Initialize file list to nullptr
|
||||||
|
newDir->subdir = createDirHierarchy(level + 1, maxLevel); // Recursively create subdirectories
|
||||||
|
newDir->next = nullptr;
|
||||||
|
|
||||||
|
// Create file list for this directory
|
||||||
|
file_test* fileHead = nullptr;
|
||||||
|
file_test* fileCurrent = nullptr;
|
||||||
|
for (int j = 0; j < 3; ++j) {
|
||||||
|
file_test* newFile = new file_test;
|
||||||
|
newFile->name = generateRandomName(6); // Generate a random name for the file
|
||||||
|
newFile->next = nullptr;
|
||||||
|
|
||||||
|
if (!fileHead) {
|
||||||
|
fileHead = newFile;
|
||||||
|
} else {
|
||||||
|
fileCurrent->next = newFile;
|
||||||
|
}
|
||||||
|
fileCurrent = newFile;
|
||||||
|
}
|
||||||
|
newDir->inFile = fileHead;
|
||||||
|
|
||||||
|
// Add the new directory to the list
|
||||||
|
if (!head) {
|
||||||
|
head = newDir;
|
||||||
|
} else {
|
||||||
|
current->next = newDir;
|
||||||
|
}
|
||||||
|
current = newDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup function for the test directory
|
||||||
|
void setupTestDirectory(dir_test** root) {
|
||||||
|
// Allocate memory for root
|
||||||
|
*root = new dir_test;
|
||||||
|
(*root)->name = strdup("/"); // use / as begin
|
||||||
|
(*root)->inFile = nullptr; // Initialize file list to nullptr
|
||||||
|
(*root)->subdir = createDirHierarchy(0, 1);
|
||||||
|
(*root)->next = nullptr;
|
||||||
|
file_test* fileHead = nullptr;
|
||||||
|
file_test* fileCurrent = nullptr;
|
||||||
|
for (int j = 0; j < 3; ++j) {
|
||||||
|
file_test* newFile = new file_test;
|
||||||
|
newFile->name = generateRandomName(6); // Generate a random name for the file
|
||||||
|
newFile->next = nullptr;
|
||||||
|
|
||||||
|
if (!fileHead) {
|
||||||
|
fileHead = newFile;
|
||||||
|
} else {
|
||||||
|
fileCurrent->next = newFile;
|
||||||
|
}
|
||||||
|
fileCurrent = newFile;
|
||||||
|
}
|
||||||
|
(*root)->inFile = fileHead;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to free a list of files
|
||||||
|
void freeFileList(file_test* fileList) {
|
||||||
|
while (fileList != nullptr) {
|
||||||
|
file_test* temp = fileList;
|
||||||
|
fileList = fileList->next;
|
||||||
|
total_free_file++;//for debug
|
||||||
|
delete[] temp->name; // Free the name string
|
||||||
|
delete temp; // Free the current file
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recursive function to free the directory hierarchy
|
||||||
|
void freeDirHierarchy(dir_test* dir) {
|
||||||
|
while (dir != nullptr) {
|
||||||
|
dir_test* temp = dir;
|
||||||
|
dir = dir->next;
|
||||||
|
total_free_dir++;//for debug
|
||||||
|
freeFileList(temp->inFile); // Free the list of files in the directory
|
||||||
|
freeDirHierarchy(temp->subdir); // Recursively free subdirectories
|
||||||
|
delete[] temp->name; // Free the name string
|
||||||
|
delete temp; // Free the current directory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to print the list of files in a directory
|
||||||
|
void printFileList(const file_test* fileList) {
|
||||||
|
const file_test* currentFile = fileList;
|
||||||
|
while (currentFile != nullptr) {
|
||||||
|
// std::cout << " File: " << currentFile->name << std::endl;
|
||||||
|
total_file_num++;
|
||||||
|
currentFile = currentFile->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void traverseDirHierarchy(const dir_test* dir, int depth = 0) {
|
||||||
|
while (dir != nullptr) {
|
||||||
|
// std::cout << "Depth " << depth << ", Directory: " << dir->name << std::endl;
|
||||||
|
total_dir_num++;//for debug
|
||||||
|
|
||||||
|
// Print files in this directory
|
||||||
|
printFileList(dir->inFile);
|
||||||
|
// Recursively traverse subdirectories
|
||||||
|
traverseDirHierarchy(dir->subdir, depth + 1);
|
||||||
|
|
||||||
|
// Go to the next directory at the same level
|
||||||
|
dir = dir->next;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user