Add compression and scanner tests; fix chunk_decompress data ownership bug, data_destroy NULL safety, chunk_compress memory leak
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
#include "test_array_list.h"
|
||||
#include "test_chunk.h"
|
||||
#include "test_compression.h"
|
||||
#include "test_config.h"
|
||||
#include "test_queue.h"
|
||||
#include "test_scanner.h"
|
||||
#include "test_shared_utils.h"
|
||||
#include "test_utils.h"
|
||||
#include <stdio.h>
|
||||
@@ -19,6 +21,8 @@ int main() {
|
||||
RUN_TEST(test_shared_utils);
|
||||
RUN_TEST(test_chunk);
|
||||
RUN_TEST(test_config);
|
||||
RUN_TEST(test_compression);
|
||||
RUN_TEST(test_scanner);
|
||||
|
||||
printf("\n\033[1;36m=== TEST SUMMARY ===\033[0m\n");
|
||||
printf("Total Tests Run: %d\n", tests_run);
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
#include "test_utils.h"
|
||||
#include "chunk.h"
|
||||
#include "data.h"
|
||||
#include "file.h"
|
||||
#include "utils.h"
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void test_data_compress_decompress_roundtrip() {
|
||||
char original[] = "Hello, World! This is test data for compression round-trip!";
|
||||
size_t len = strlen(original);
|
||||
|
||||
char *buf = malloc(len);
|
||||
memcpy(buf, original, len);
|
||||
Data *original_data = data_create(buf, len);
|
||||
EXPECT_NOT_NULL(original_data);
|
||||
|
||||
Data *compressed = data_compress(original_data, 3);
|
||||
EXPECT_NOT_NULL(compressed);
|
||||
|
||||
Data *decompressed = data_decompress(compressed);
|
||||
EXPECT_NOT_NULL(decompressed);
|
||||
EXPECT_EQ_INT((int)decompressed->size, (int)len);
|
||||
EXPECT_EQ_INT(memcmp(decompressed->data, original, len), 0);
|
||||
|
||||
data_destroy(original_data);
|
||||
data_destroy(compressed);
|
||||
data_destroy(decompressed);
|
||||
}
|
||||
|
||||
static void test_data_compress_decompress_large() {
|
||||
size_t size = 1024 * 10;
|
||||
char *original = malloc(size);
|
||||
EXPECT_NOT_NULL(original);
|
||||
for (size_t i = 0; i < size; i++)
|
||||
original[i] = (char)(i % 256);
|
||||
|
||||
Data *original_data = data_create(original, size);
|
||||
EXPECT_NOT_NULL(original_data);
|
||||
|
||||
Data *compressed = data_compress(original_data, 1);
|
||||
EXPECT_NOT_NULL(compressed);
|
||||
|
||||
Data *decompressed = data_decompress(compressed);
|
||||
EXPECT_NOT_NULL(decompressed);
|
||||
EXPECT_EQ_INT((int)decompressed->size, (int)size);
|
||||
EXPECT_EQ_INT(memcmp(decompressed->data, original, size), 0);
|
||||
|
||||
data_destroy(original_data);
|
||||
data_destroy(compressed);
|
||||
data_destroy(decompressed);
|
||||
}
|
||||
|
||||
static void test_chunk_compress_decompress_roundtrip() {
|
||||
char *path1 = "temp_comp_test_1.txt";
|
||||
char *content1 = "chunk compression test file 1";
|
||||
unsigned long long len1 = strlen(content1);
|
||||
|
||||
char *path2 = "temp_comp_test_2.txt";
|
||||
char *content2 = "chunk compression test file 2 with more data";
|
||||
unsigned long long len2 = strlen(content2);
|
||||
|
||||
to_disk(path1, content1, len1);
|
||||
to_disk(path2, content2, len2);
|
||||
|
||||
struct stat st1, st2;
|
||||
EXPECT_EQ_INT(stat(path1, &st1), 0);
|
||||
EXPECT_EQ_INT(stat(path2, &st2), 0);
|
||||
|
||||
File *f1 = file_create(path1, &st1);
|
||||
File *f2 = file_create(path2, &st2);
|
||||
EXPECT_NOT_NULL(f1);
|
||||
EXPECT_NOT_NULL(f2);
|
||||
|
||||
file_load_data(f1);
|
||||
file_load_data(f2);
|
||||
|
||||
File *files[2] = {f1, f2};
|
||||
Chunk *chunk = chunk_create(files, 2);
|
||||
EXPECT_NOT_NULL(chunk);
|
||||
|
||||
Data *compressed = chunk_compress(chunk, 3);
|
||||
EXPECT_NOT_NULL(compressed);
|
||||
|
||||
Chunk *decompressed_chunk = chunk_decompress(compressed);
|
||||
EXPECT_NOT_NULL(decompressed_chunk);
|
||||
EXPECT_EQ_INT(decompressed_chunk->element_count, 2);
|
||||
|
||||
EXPECT_EQ_STR(decompressed_chunk->items[0]->path, path1);
|
||||
EXPECT_EQ_INT((int)decompressed_chunk->items[0]->data->size, (int)len1);
|
||||
EXPECT_EQ_INT(memcmp(decompressed_chunk->items[0]->data->data, content1, len1), 0);
|
||||
|
||||
EXPECT_EQ_STR(decompressed_chunk->items[1]->path, path2);
|
||||
EXPECT_EQ_INT((int)decompressed_chunk->items[1]->data->size, (int)len2);
|
||||
EXPECT_EQ_INT(memcmp(decompressed_chunk->items[1]->data->data, content2, len2), 0);
|
||||
|
||||
chunk_destroy(chunk);
|
||||
data_destroy(compressed);
|
||||
chunk_destroy(decompressed_chunk);
|
||||
|
||||
unlink(path1);
|
||||
unlink(path2);
|
||||
}
|
||||
|
||||
void test_compression() {
|
||||
test_data_compress_decompress_roundtrip();
|
||||
test_data_compress_decompress_large();
|
||||
test_chunk_compress_decompress_roundtrip();
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef TEST_COMPRESSION_H
|
||||
#define TEST_COMPRESSION_H
|
||||
|
||||
void test_compression();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,124 @@
|
||||
#include "test_utils.h"
|
||||
#include "scanner.h"
|
||||
#include "file.h"
|
||||
#include "utils.h"
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void create_test_file(const char *path, const char *content) {
|
||||
to_disk(path, content, strlen(content));
|
||||
}
|
||||
|
||||
static void test_scanner_single_file() {
|
||||
const char *dir = "test_scan_dir_single";
|
||||
const char *file1 = "test_scan_dir_single/file1.txt";
|
||||
const char *content1 = "hello scanner";
|
||||
|
||||
mkdir(dir, 0755);
|
||||
create_test_file(file1, content1);
|
||||
|
||||
DirectoryScanner *scanner = directory_scanner_create((char *)dir);
|
||||
EXPECT_NOT_NULL(scanner);
|
||||
|
||||
Chunk *chunk = directory_scanner_next(scanner);
|
||||
EXPECT_NOT_NULL(chunk);
|
||||
EXPECT_EQ_INT(chunk->element_count, 1);
|
||||
EXPECT_EQ_STR(chunk->items[0]->path, file1);
|
||||
|
||||
Chunk *next = directory_scanner_next(scanner);
|
||||
EXPECT_NULL(next);
|
||||
|
||||
chunk_destroy(chunk);
|
||||
directory_scanner_destroy(scanner);
|
||||
unlink(file1);
|
||||
rmdir(dir);
|
||||
}
|
||||
|
||||
static void test_scanner_multiple_files() {
|
||||
const char *dir = "test_scan_dir_multi";
|
||||
const char *file1 = "test_scan_dir_multi/a.txt";
|
||||
const char *file2 = "test_scan_dir_multi/b.txt";
|
||||
const char *content1 = "alpha";
|
||||
const char *content2 = "beta";
|
||||
|
||||
mkdir(dir, 0755);
|
||||
create_test_file(file1, content1);
|
||||
create_test_file(file2, content2);
|
||||
|
||||
DirectoryScanner *scanner = directory_scanner_create((char *)dir);
|
||||
EXPECT_NOT_NULL(scanner);
|
||||
|
||||
Chunk *chunk = directory_scanner_next(scanner);
|
||||
EXPECT_NOT_NULL(chunk);
|
||||
EXPECT_EQ_INT(chunk->element_count, 2);
|
||||
|
||||
int found1 = 0, found2 = 0;
|
||||
for (int i = 0; i < chunk->element_count; i++) {
|
||||
if (strcmp(chunk->items[i]->path, file1) == 0) found1 = 1;
|
||||
if (strcmp(chunk->items[i]->path, file2) == 0) found2 = 1;
|
||||
}
|
||||
EXPECT_TRUE(found1);
|
||||
EXPECT_TRUE(found2);
|
||||
|
||||
Chunk *next = directory_scanner_next(scanner);
|
||||
EXPECT_NULL(next);
|
||||
|
||||
chunk_destroy(chunk);
|
||||
directory_scanner_destroy(scanner);
|
||||
unlink(file1);
|
||||
unlink(file2);
|
||||
rmdir(dir);
|
||||
}
|
||||
|
||||
static void test_scanner_subdirectory() {
|
||||
const char *root = "test_scan_sub";
|
||||
const char *sub = "test_scan_sub/sub";
|
||||
const char *root_file = "test_scan_sub/root.txt";
|
||||
const char *sub_file = "test_scan_sub/sub/sub_file.txt";
|
||||
const char *content = "nested content";
|
||||
|
||||
mkdir(root, 0755);
|
||||
mkdir(sub, 0755);
|
||||
create_test_file(root_file, content);
|
||||
create_test_file(sub_file, content);
|
||||
|
||||
DirectoryScanner *scanner = directory_scanner_create((char *)root);
|
||||
EXPECT_NOT_NULL(scanner);
|
||||
|
||||
int total_files = 0;
|
||||
Chunk *chunk;
|
||||
while ((chunk = directory_scanner_next(scanner)) != NULL) {
|
||||
total_files += chunk->element_count;
|
||||
chunk_destroy(chunk);
|
||||
}
|
||||
EXPECT_EQ_INT(total_files, 2);
|
||||
|
||||
directory_scanner_destroy(scanner);
|
||||
unlink(root_file);
|
||||
unlink(sub_file);
|
||||
rmdir(sub);
|
||||
rmdir(root);
|
||||
}
|
||||
|
||||
static void test_scanner_empty_directory() {
|
||||
const char *dir = "test_scan_empty";
|
||||
|
||||
mkdir(dir, 0755);
|
||||
|
||||
DirectoryScanner *scanner = directory_scanner_create((char *)dir);
|
||||
EXPECT_NOT_NULL(scanner);
|
||||
|
||||
Chunk *chunk = directory_scanner_next(scanner);
|
||||
EXPECT_NULL(chunk);
|
||||
|
||||
directory_scanner_destroy(scanner);
|
||||
rmdir(dir);
|
||||
}
|
||||
|
||||
void test_scanner() {
|
||||
test_scanner_single_file();
|
||||
test_scanner_multiple_files();
|
||||
test_scanner_subdirectory();
|
||||
test_scanner_empty_directory();
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef TEST_SCANNER_H
|
||||
#define TEST_SCANNER_H
|
||||
|
||||
void test_scanner();
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user