test: Add 1, update 4 and remove 1 files
This commit is contained in:
BIN
dshash/dshash
BIN
dshash/dshash
Binary file not shown.
BIN
dshash/dshash.o
BIN
dshash/dshash.o
Binary file not shown.
BIN
dshash/main.o
BIN
dshash/main.o
Binary file not shown.
251
tests/test.sh
251
tests/test.sh
@@ -14,10 +14,33 @@ cd "$PROJECT_DIR/dshash"
|
|||||||
make clean > /dev/null 2>&1
|
make clean > /dev/null 2>&1
|
||||||
make > /dev/null 2>&1
|
make > /dev/null 2>&1
|
||||||
|
|
||||||
|
TOTAL_PASSED=0
|
||||||
|
TOTAL_FAILED=0
|
||||||
|
|
||||||
|
# =====================================
|
||||||
|
# SECTION 1: Library Unit Tests
|
||||||
|
# =====================================
|
||||||
|
echo ""
|
||||||
|
echo "=== Section 1: Library Unit Tests ==="
|
||||||
echo "Building test program..."
|
echo "Building test program..."
|
||||||
cd "$SCRIPT_DIR"
|
cd "$SCRIPT_DIR"
|
||||||
g++ -std=c++17 -o test_lib test_lib.cpp ../src/dshash.cpp -I../src
|
g++ -std=c++17 -o test_lib test_lib.cpp ../src/dshash.cpp -I../src
|
||||||
|
|
||||||
|
./test_lib
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "✓ All library tests passed"
|
||||||
|
TOTAL_PASSED=$((TOTAL_PASSED + 7))
|
||||||
|
else
|
||||||
|
echo "✗ Library tests failed"
|
||||||
|
TOTAL_FAILED=$((TOTAL_FAILED + 1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
# =====================================
|
||||||
|
# SECTION 2: Basic Utility Tests
|
||||||
|
# =====================================
|
||||||
|
echo ""
|
||||||
|
echo "=== Section 2: Basic Utility Tests ==="
|
||||||
|
|
||||||
FAILED=0
|
FAILED=0
|
||||||
PASSED=0
|
PASSED=0
|
||||||
|
|
||||||
@@ -37,20 +60,6 @@ run_test() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Running library tests..."
|
|
||||||
./test_lib
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
echo "✓ All library tests passed"
|
|
||||||
PASSED=$((PASSED + 1))
|
|
||||||
else
|
|
||||||
echo "✗ Library tests failed"
|
|
||||||
FAILED=$((FAILED + 1))
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Running utility tests..."
|
|
||||||
|
|
||||||
echo -n "abc" > "$TEMP_DIR/test1.txt"
|
echo -n "abc" > "$TEMP_DIR/test1.txt"
|
||||||
HASH=$($DSHASH_BIN "$TEMP_DIR/test1.txt")
|
HASH=$($DSHASH_BIN "$TEMP_DIR/test1.txt")
|
||||||
run_test "Hash of 'abc'" "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" "$HASH"
|
run_test "Hash of 'abc'" "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" "$HASH"
|
||||||
@@ -86,12 +95,222 @@ else
|
|||||||
run_test "Verbose mode for directory" "works" "failed"
|
run_test "Verbose mode for directory" "works" "failed"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
TOTAL_PASSED=$((TOTAL_PASSED + PASSED))
|
||||||
|
TOTAL_FAILED=$((TOTAL_FAILED + FAILED))
|
||||||
|
|
||||||
|
# =====================================
|
||||||
|
# SECTION 3: System SHA256 Comparison
|
||||||
|
# =====================================
|
||||||
|
echo ""
|
||||||
|
echo "=== Section 3: System SHA256 Comparison ==="
|
||||||
|
|
||||||
|
FAILED=0
|
||||||
|
PASSED=0
|
||||||
|
|
||||||
|
compare_with_system() {
|
||||||
|
local test_name="$1"
|
||||||
|
local file_path="$2"
|
||||||
|
|
||||||
|
local our_hash=$($DSHASH_BIN "$file_path")
|
||||||
|
local system_hash=$(sha256sum "$file_path" | cut -d' ' -f1)
|
||||||
|
|
||||||
|
if [ "$our_hash" = "$system_hash" ]; then
|
||||||
|
echo "✓ $test_name"
|
||||||
|
PASSED=$((PASSED + 1))
|
||||||
|
else
|
||||||
|
echo "✗ $test_name"
|
||||||
|
echo " Our hash: $our_hash"
|
||||||
|
echo " System hash: $system_hash"
|
||||||
|
FAILED=$((FAILED + 1))
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test various file types
|
||||||
|
echo -n "a" > "$TEMP_DIR/single.txt"
|
||||||
|
compare_with_system "Single character" "$TEMP_DIR/single.txt"
|
||||||
|
|
||||||
|
printf "\x00\x01\x02\x03\xFF\xFE\xFD" > "$TEMP_DIR/binary.bin"
|
||||||
|
compare_with_system "Binary data" "$TEMP_DIR/binary.bin"
|
||||||
|
|
||||||
|
dd if=/dev/zero bs=1024 count=1024 2>/dev/null | tr '\0' 'A' > "$TEMP_DIR/large.txt"
|
||||||
|
compare_with_system "Large file (1MB)" "$TEMP_DIR/large.txt"
|
||||||
|
|
||||||
|
echo -n "!@#$%^&*()_+-=[]{}|;':\",./<>?" > "$TEMP_DIR/special.txt"
|
||||||
|
compare_with_system "Special characters" "$TEMP_DIR/special.txt"
|
||||||
|
|
||||||
|
echo -n "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" > "$TEMP_DIR/64bytes.txt"
|
||||||
|
compare_with_system "Exactly 64 bytes" "$TEMP_DIR/64bytes.txt"
|
||||||
|
|
||||||
|
echo -n "Hello 世界 🌍 Здравствуй мир" > "$TEMP_DIR/unicode.txt"
|
||||||
|
compare_with_system "Unicode text" "$TEMP_DIR/unicode.txt"
|
||||||
|
|
||||||
|
for i in {0..255}; do
|
||||||
|
printf "\\x$(printf %02x $i)"
|
||||||
|
done > "$TEMP_DIR/allbytes.bin"
|
||||||
|
compare_with_system "All byte values 0-255" "$TEMP_DIR/allbytes.bin"
|
||||||
|
|
||||||
|
TOTAL_PASSED=$((TOTAL_PASSED + PASSED))
|
||||||
|
TOTAL_FAILED=$((TOTAL_FAILED + FAILED))
|
||||||
|
|
||||||
|
# =====================================
|
||||||
|
# SECTION 4: NIST Test Vectors
|
||||||
|
# =====================================
|
||||||
|
echo ""
|
||||||
|
echo "=== Section 4: NIST Test Vectors ==="
|
||||||
|
|
||||||
|
FAILED=0
|
||||||
|
PASSED=0
|
||||||
|
|
||||||
|
# NIST test vectors
|
||||||
|
declare -a VECTORS=(
|
||||||
|
"|e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||||
|
"abc|ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
|
||||||
|
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq|248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
|
||||||
|
"a|ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
|
||||||
|
)
|
||||||
|
|
||||||
|
for vector in "${VECTORS[@]}"; do
|
||||||
|
IFS='|' read -r input expected <<< "$vector"
|
||||||
|
echo -n "$input" > "$TEMP_DIR/test.txt"
|
||||||
|
our_hash=$($DSHASH_BIN "$TEMP_DIR/test.txt")
|
||||||
|
|
||||||
|
if [ "$our_hash" = "$expected" ]; then
|
||||||
|
if [ -z "$input" ]; then
|
||||||
|
echo "✓ Empty string"
|
||||||
|
elif [ ${#input} -gt 20 ]; then
|
||||||
|
echo "✓ '${input:0:20}...'"
|
||||||
|
else
|
||||||
|
echo "✓ '$input'"
|
||||||
|
fi
|
||||||
|
PASSED=$((PASSED + 1))
|
||||||
|
else
|
||||||
|
echo "✗ Failed for input: '$input'"
|
||||||
|
echo " Expected: $expected"
|
||||||
|
echo " Got: $our_hash"
|
||||||
|
FAILED=$((FAILED + 1))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Special test: one million 'a' characters
|
||||||
|
perl -e 'print "a" x 1000000' > "$TEMP_DIR/million_a.txt"
|
||||||
|
our_hash=$($DSHASH_BIN "$TEMP_DIR/million_a.txt")
|
||||||
|
expected="cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"
|
||||||
|
|
||||||
|
if [ "$our_hash" = "$expected" ]; then
|
||||||
|
echo "✓ One million 'a' characters"
|
||||||
|
PASSED=$((PASSED + 1))
|
||||||
|
else
|
||||||
|
echo "✗ One million 'a' characters"
|
||||||
|
FAILED=$((FAILED + 1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
TOTAL_PASSED=$((TOTAL_PASSED + PASSED))
|
||||||
|
TOTAL_FAILED=$((TOTAL_FAILED + FAILED))
|
||||||
|
|
||||||
|
# =====================================
|
||||||
|
# SECTION 5: Stress Tests
|
||||||
|
# =====================================
|
||||||
|
echo ""
|
||||||
|
echo "=== Section 5: Stress Tests ==="
|
||||||
|
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
g++ -std=c++17 -O2 -o test_stress test_stress.cpp ../src/dshash.cpp -I../src 2>/dev/null
|
||||||
|
|
||||||
|
if ./test_stress > /dev/null 2>&1; then
|
||||||
|
echo "✓ All stress tests passed (8 tests)"
|
||||||
|
TOTAL_PASSED=$((TOTAL_PASSED + 8))
|
||||||
|
else
|
||||||
|
echo "✗ Stress tests failed"
|
||||||
|
TOTAL_FAILED=$((TOTAL_FAILED + 1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f test_stress test_lib
|
||||||
|
|
||||||
|
# =====================================
|
||||||
|
# SECTION 6: Edge Cases
|
||||||
|
# =====================================
|
||||||
|
echo ""
|
||||||
|
echo "=== Section 6: Edge Cases ==="
|
||||||
|
|
||||||
|
FAILED=0
|
||||||
|
PASSED=0
|
||||||
|
|
||||||
|
# File with spaces in name
|
||||||
|
echo -n "test" > "$TEMP_DIR/file with spaces.txt"
|
||||||
|
OUR_HASH=$($DSHASH_BIN "$TEMP_DIR/file with spaces.txt")
|
||||||
|
SYSTEM_HASH=$(sha256sum "$TEMP_DIR/file with spaces.txt" | cut -d' ' -f1)
|
||||||
|
if [ "$OUR_HASH" = "$SYSTEM_HASH" ]; then
|
||||||
|
echo "✓ File with spaces in name"
|
||||||
|
PASSED=$((PASSED + 1))
|
||||||
|
else
|
||||||
|
echo "✗ File with spaces in name"
|
||||||
|
FAILED=$((FAILED + 1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Symlink handling
|
||||||
|
echo -n "target" > "$TEMP_DIR/target.txt"
|
||||||
|
ln -s "$TEMP_DIR/target.txt" "$TEMP_DIR/link.txt"
|
||||||
|
OUR_HASH=$($DSHASH_BIN "$TEMP_DIR/link.txt")
|
||||||
|
SYSTEM_HASH=$(sha256sum "$TEMP_DIR/link.txt" | cut -d' ' -f1)
|
||||||
|
if [ "$OUR_HASH" = "$SYSTEM_HASH" ]; then
|
||||||
|
echo "✓ Symlink handling"
|
||||||
|
PASSED=$((PASSED + 1))
|
||||||
|
else
|
||||||
|
echo "✗ Symlink handling"
|
||||||
|
FAILED=$((FAILED + 1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 55 bytes (padding edge case)
|
||||||
|
echo -n "0123456789abcdef0123456789abcdef0123456789abcdef0123456" > "$TEMP_DIR/55bytes.txt"
|
||||||
|
compare_with_system "55 bytes (padding edge)" "$TEMP_DIR/55bytes.txt"
|
||||||
|
|
||||||
|
# 56 bytes (padding edge case)
|
||||||
|
echo -n "0123456789abcdef0123456789abcdef0123456789abcdef01234567" > "$TEMP_DIR/56bytes.txt"
|
||||||
|
compare_with_system "56 bytes (padding edge)" "$TEMP_DIR/56bytes.txt"
|
||||||
|
|
||||||
|
TOTAL_PASSED=$((TOTAL_PASSED + PASSED))
|
||||||
|
TOTAL_FAILED=$((TOTAL_FAILED + FAILED))
|
||||||
|
|
||||||
|
# =====================================
|
||||||
|
# SECTION 7: Performance Test
|
||||||
|
# =====================================
|
||||||
|
echo ""
|
||||||
|
echo "=== Section 7: Performance Test ==="
|
||||||
|
|
||||||
|
# Create a 10MB file
|
||||||
|
dd if=/dev/urandom bs=1024 count=10240 of="$TEMP_DIR/10mb.bin" 2>/dev/null
|
||||||
|
|
||||||
|
# Time our implementation
|
||||||
|
START=$(date +%s%N)
|
||||||
|
OUR_HASH=$($DSHASH_BIN "$TEMP_DIR/10mb.bin")
|
||||||
|
END=$(date +%s%N)
|
||||||
|
OUR_TIME=$(( (END - START) / 1000000 ))
|
||||||
|
|
||||||
|
# Time system sha256sum
|
||||||
|
START=$(date +%s%N)
|
||||||
|
SYSTEM_HASH=$(sha256sum "$TEMP_DIR/10mb.bin" | cut -d' ' -f1)
|
||||||
|
END=$(date +%s%N)
|
||||||
|
SYSTEM_TIME=$(( (END - START) / 1000000 ))
|
||||||
|
|
||||||
|
if [ "$OUR_HASH" = "$SYSTEM_HASH" ]; then
|
||||||
|
echo "✓ 10MB file hash matches"
|
||||||
|
echo " Our time: ${OUR_TIME}ms"
|
||||||
|
echo " System time: ${SYSTEM_TIME}ms"
|
||||||
|
TOTAL_PASSED=$((TOTAL_PASSED + 1))
|
||||||
|
else
|
||||||
|
echo "✗ 10MB file hash mismatch"
|
||||||
|
TOTAL_FAILED=$((TOTAL_FAILED + 1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
# =====================================
|
||||||
|
# FINAL SUMMARY
|
||||||
|
# =====================================
|
||||||
echo ""
|
echo ""
|
||||||
echo "========================================="
|
echo "========================================="
|
||||||
echo "Test Results: $PASSED passed, $FAILED failed"
|
echo "Test Results: $TOTAL_PASSED passed, $TOTAL_FAILED failed"
|
||||||
echo "========================================="
|
echo "========================================="
|
||||||
|
|
||||||
if [ $FAILED -eq 0 ]; then
|
if [ $TOTAL_FAILED -eq 0 ]; then
|
||||||
echo "All tests passed!"
|
echo "All tests passed!"
|
||||||
exit 0
|
exit 0
|
||||||
else
|
else
|
||||||
|
BIN
tests/test_lib
BIN
tests/test_lib
Binary file not shown.
276
tests/test_stress.cpp
Normal file
276
tests/test_stress.cpp
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
#include "../src/dshash.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <cassert>
|
||||||
|
#include <fstream>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <chrono>
|
||||||
|
#include <random>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
void test_incremental_vs_single() {
|
||||||
|
std::cout << "Testing incremental vs single update..." << std::endl;
|
||||||
|
|
||||||
|
// Generate random data
|
||||||
|
std::random_device rd;
|
||||||
|
std::mt19937 gen(rd());
|
||||||
|
std::uniform_int_distribution<> dis(0, 255);
|
||||||
|
|
||||||
|
std::vector<uint8_t> data(10000);
|
||||||
|
for (auto& byte : data) {
|
||||||
|
byte = dis(gen);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash all at once
|
||||||
|
DSHash hasher1(std::string(data.begin(), data.end()));
|
||||||
|
std::string hash1 = hasher1.toString();
|
||||||
|
|
||||||
|
// Hash incrementally in various chunk sizes
|
||||||
|
std::vector<size_t> chunk_sizes = {1, 7, 13, 64, 100, 1000, 3333};
|
||||||
|
|
||||||
|
for (size_t chunk_size : chunk_sizes) {
|
||||||
|
// Create a new hasher and initialize it properly
|
||||||
|
std::string accumulated;
|
||||||
|
for (size_t i = 0; i < data.size(); i += chunk_size) {
|
||||||
|
size_t len = std::min(chunk_size, data.size() - i);
|
||||||
|
accumulated.append(data.begin() + i, data.begin() + i + len);
|
||||||
|
}
|
||||||
|
|
||||||
|
DSHash hasher2(accumulated);
|
||||||
|
std::string hash2 = hasher2.toString();
|
||||||
|
|
||||||
|
if (hash1 != hash2) {
|
||||||
|
std::cerr << "✗ Mismatch with chunk size " << chunk_size << std::endl;
|
||||||
|
std::cerr << " Single: " << hash1 << std::endl;
|
||||||
|
std::cerr << " Chunked: " << hash2 << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "✓ All chunk sizes produce identical results" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_boundary_conditions() {
|
||||||
|
std::cout << "Testing boundary conditions..." << std::endl;
|
||||||
|
|
||||||
|
// Test data sizes around block boundaries
|
||||||
|
std::vector<size_t> sizes = {
|
||||||
|
0, 1, 31, 32, 33, // Near 32 bytes
|
||||||
|
54, 55, 56, 57, // Near padding boundary
|
||||||
|
63, 64, 65, // Block boundary
|
||||||
|
119, 120, 121, // Near 2 blocks
|
||||||
|
127, 128, 129, // 2 block boundary
|
||||||
|
511, 512, 513, // 8 block boundary
|
||||||
|
1023, 1024, 1025 // 16 block boundary
|
||||||
|
};
|
||||||
|
|
||||||
|
for (size_t size : sizes) {
|
||||||
|
std::string data(size, 'X');
|
||||||
|
DSHash hasher(data);
|
||||||
|
std::string hash = hasher.toString();
|
||||||
|
|
||||||
|
// Just verify it doesn't crash and produces valid hash
|
||||||
|
assert(hash.length() == 64);
|
||||||
|
for (char c : hash) {
|
||||||
|
assert((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "✓ All boundary conditions handled correctly" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_large_files() {
|
||||||
|
std::cout << "Testing large file handling..." << std::endl;
|
||||||
|
|
||||||
|
std::string tempFile = "/tmp/test_large.bin";
|
||||||
|
|
||||||
|
// Test various large sizes
|
||||||
|
std::vector<size_t> mb_sizes = {1, 5, 10, 50};
|
||||||
|
|
||||||
|
for (size_t mb : mb_sizes) {
|
||||||
|
size_t size = mb * 1024 * 1024;
|
||||||
|
|
||||||
|
// Create file with pattern
|
||||||
|
std::ofstream out(tempFile, std::ios::binary);
|
||||||
|
std::vector<uint8_t> buffer(8192);
|
||||||
|
for (size_t i = 0; i < buffer.size(); i++) {
|
||||||
|
buffer[i] = i % 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t written = 0;
|
||||||
|
while (written < size) {
|
||||||
|
size_t to_write = std::min(buffer.size(), size - written);
|
||||||
|
out.write(reinterpret_cast<char*>(buffer.data()), to_write);
|
||||||
|
written += to_write;
|
||||||
|
}
|
||||||
|
out.close();
|
||||||
|
|
||||||
|
// Hash the file
|
||||||
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
|
DSHash hasher{std::filesystem::path(tempFile)};
|
||||||
|
std::string hash = hasher.toString();
|
||||||
|
auto end = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
|
||||||
|
|
||||||
|
std::cout << " " << mb << "MB file: " << duration.count() << "ms";
|
||||||
|
|
||||||
|
// Verify hash format
|
||||||
|
assert(hash.length() == 64);
|
||||||
|
for (char c : hash) {
|
||||||
|
assert((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << " ✓" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::filesystem::remove(tempFile);
|
||||||
|
std::cout << "✓ Large files handled successfully" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_special_characters_in_strings() {
|
||||||
|
std::cout << "Testing special characters..." << std::endl;
|
||||||
|
|
||||||
|
struct TestCase {
|
||||||
|
std::string description;
|
||||||
|
std::string input;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<TestCase> cases = {
|
||||||
|
{"Null bytes", std::string("abc\0def", 7)},
|
||||||
|
{"High ASCII", "\x80\x90\xA0\xB0\xC0\xD0\xE0\xF0"},
|
||||||
|
{"Control characters", "\x01\x02\x03\x04\x05\x06\x07\x08"},
|
||||||
|
{"Mixed binary", std::string("\x00\xFF\x00\xFF", 4)},
|
||||||
|
{"UTF-8 emoji", "🎉🎊🎈🎆🎇"},
|
||||||
|
{"Tabs and newlines", "line1\t\tline2\n\rline3"},
|
||||||
|
{"Quotes and escapes", "\"'\\`${}[]()"},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto& tc : cases) {
|
||||||
|
DSHash hasher(tc.input);
|
||||||
|
std::string hash = hasher.toString();
|
||||||
|
|
||||||
|
// Verify valid hash
|
||||||
|
assert(hash.length() == 64);
|
||||||
|
for (char c : hash) {
|
||||||
|
assert((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << " " << tc.description << " ✓" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "✓ Special characters handled correctly" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_consistency() {
|
||||||
|
std::cout << "Testing hash consistency..." << std::endl;
|
||||||
|
|
||||||
|
// Test that same input always produces same output
|
||||||
|
std::string test_data = "consistency test data";
|
||||||
|
std::string first_hash;
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
DSHash hasher(test_data);
|
||||||
|
std::string hash = hasher.toString();
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
first_hash = hash;
|
||||||
|
} else {
|
||||||
|
assert(hash == first_hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "✓ Hash is consistent across 100 iterations" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_known_collisions() {
|
||||||
|
std::cout << "Testing uniqueness..." << std::endl;
|
||||||
|
|
||||||
|
// Generate many similar strings and verify they produce different hashes
|
||||||
|
std::set<std::string> hashes;
|
||||||
|
|
||||||
|
for (int i = 0; i < 1000; i++) {
|
||||||
|
std::string data = "test" + std::to_string(i);
|
||||||
|
DSHash hasher(data);
|
||||||
|
std::string hash = hasher.toString();
|
||||||
|
|
||||||
|
if (hashes.find(hash) != hashes.end()) {
|
||||||
|
std::cerr << "✗ Collision found for: " << data << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
hashes.insert(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "✓ 1000 similar strings produced unique hashes" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_empty_directory() {
|
||||||
|
std::cout << "Testing empty directory..." << std::endl;
|
||||||
|
|
||||||
|
std::filesystem::path tempDir = "/tmp/test_empty_dir";
|
||||||
|
std::filesystem::create_directories(tempDir);
|
||||||
|
|
||||||
|
DSHash hasher(tempDir);
|
||||||
|
std::string hash = hasher.toString();
|
||||||
|
|
||||||
|
// Should produce valid hash for empty directory
|
||||||
|
assert(hash.length() == 64);
|
||||||
|
|
||||||
|
std::filesystem::remove_all(tempDir);
|
||||||
|
std::cout << "✓ Empty directory handled correctly" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_directory_with_subdirs() {
|
||||||
|
std::cout << "Testing complex directory structure..." << std::endl;
|
||||||
|
|
||||||
|
std::filesystem::path tempDir = "/tmp/test_complex_dir";
|
||||||
|
std::filesystem::remove_all(tempDir);
|
||||||
|
|
||||||
|
// Create complex structure
|
||||||
|
std::filesystem::create_directories(tempDir / "a" / "b" / "c");
|
||||||
|
std::filesystem::create_directories(tempDir / "x" / "y");
|
||||||
|
std::filesystem::create_directories(tempDir / "empty");
|
||||||
|
|
||||||
|
// Add files at various levels
|
||||||
|
std::ofstream(tempDir / "root.txt") << "root";
|
||||||
|
std::ofstream(tempDir / "a" / "file_a.txt") << "a";
|
||||||
|
std::ofstream(tempDir / "a" / "b" / "file_b.txt") << "b";
|
||||||
|
std::ofstream(tempDir / "a" / "b" / "c" / "file_c.txt") << "c";
|
||||||
|
std::ofstream(tempDir / "x" / "file_x.txt") << "x";
|
||||||
|
std::ofstream(tempDir / "x" / "y" / "file_y.txt") << "y";
|
||||||
|
|
||||||
|
// Hash multiple times to ensure consistency
|
||||||
|
std::string hash1, hash2;
|
||||||
|
|
||||||
|
DSHash hasher1(tempDir);
|
||||||
|
hash1 = hasher1.toString();
|
||||||
|
|
||||||
|
DSHash hasher2(tempDir);
|
||||||
|
hash2 = hasher2.toString();
|
||||||
|
|
||||||
|
assert(hash1 == hash2);
|
||||||
|
|
||||||
|
std::filesystem::remove_all(tempDir);
|
||||||
|
std::cout << "✓ Complex directory structure handled correctly" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
try {
|
||||||
|
std::cout << "\n=== Running stress tests ===\n" << std::endl;
|
||||||
|
|
||||||
|
test_incremental_vs_single();
|
||||||
|
test_boundary_conditions();
|
||||||
|
test_large_files();
|
||||||
|
test_special_characters_in_strings();
|
||||||
|
test_consistency();
|
||||||
|
test_known_collisions();
|
||||||
|
test_empty_directory();
|
||||||
|
test_directory_with_subdirs();
|
||||||
|
|
||||||
|
std::cout << "\n✓ All stress tests passed!\n" << std::endl;
|
||||||
|
return 0;
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
std::cerr << "\n✗ Test failed with exception: " << e.what() << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user