This commit is contained in:
2023-06-02 12:51:08 +02:00
commit 0e355fbe42
142 changed files with 10281 additions and 0 deletions

39
tests/BuzhashTest.cpp Normal file
View File

@@ -0,0 +1,39 @@
//
// Created by Stepan Usatiuk on 27.04.2023.
//
#include "BuzhashTest.h"
#include "../src/chunkers/Buzhash.h"
std::unique_ptr<TestGroup> BuzhashTest::operator()() {
auto tg = std::make_unique<TestGroup>("Buzhash tests");
tg->addTest(std::make_unique<Test>("Simple buzhash test", std::function<bool()>([]() {
std::string loremipsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
for (int i = 15; i < 49; i++) {
Buzhash b(i);
std::string p1 = "reprehenderit in voluptate velit esse cillum dolore";
for (auto c: p1) b.feed(static_cast<uint8_t>(c));
auto h1 = b.get();
Buzhash b2(i);
bool h1found = false;
for (int i = 0; i < loremipsum.length(); i++) {
b2.feed((uint8_t) loremipsum[i]);
if (b2.get() == h1) {
HelpfulAssert<int>()(i, loremipsum.find("e eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non p"));
h1found = true;
break;
}
}
HelpfulAssert<bool>()(h1found, true);
}
return true;
})));
return tg;
}

16
tests/BuzhashTest.h Normal file
View File

@@ -0,0 +1,16 @@
//
// Created by Stepan Usatiuk on 27.04.2023.
//
#ifndef SEMBACKUP_BUZHASHTEST_H
#define SEMBACKUP_BUZHASHTEST_H
#include "utils/TestGroupGenerator.h"
class BuzhashTest : public TestGroupGenerator {
public:
std::unique_ptr<TestGroup> operator()() override;
};
#endif//SEMBACKUP_BUZHASHTEST_H

30
tests/CLITestWrapper.cpp Normal file
View File

@@ -0,0 +1,30 @@
//
// Created by Stepan Usatiuk on 10.05.2023.
//
#include "CLITestWrapper.h"
#include "utils/Cleaner.h"
std::unique_ptr<TestGroup> CLITestWrapper::operator()() {
auto tg = std::make_unique<TestGroup>("CLI tests");
tg->addTest(std::make_unique<Test>("Test backup", std::function<bool()>([]() {
int ret = system("../tests/clitests/backup.sh");
HelpfulAssert<int>()(WEXITSTATUS(ret), 0);
return true;
})));
tg->addTest(std::make_unique<Test>("Test ignore", std::function<bool()>([]() {
int ret = system("../tests/clitests/ignore.sh");
HelpfulAssert<int>()(WEXITSTATUS(ret), 0);
return true;
})));
tg->addTest(std::make_unique<Test>("Test diff", std::function<bool()>([]() {
int ret = system("../tests/clitests/diff.sh");
HelpfulAssert<int>()(WEXITSTATUS(ret), 0);
return true;
})));
return tg;
}

15
tests/CLITestWrapper.h Normal file
View File

@@ -0,0 +1,15 @@
//
// Created by Stepan Usatiuk on 10.05.2023.
//
#ifndef SEMBACKUP_CLITESTWRAPPER_H
#define SEMBACKUP_CLITESTWRAPPER_H
#include "utils/TestGroupGenerator.h"
class CLITestWrapper : public TestGroupGenerator {
public:
std::unique_ptr<TestGroup> operator()() override;
};
#endif//SEMBACKUP_CLITESTWRAPPER_H

293
tests/clitests/backup.sh Executable file
View File

@@ -0,0 +1,293 @@
#!/bin/bash
TESTSIZE=16
CMD=./sembackup
rm -rf testdata
rm -rf testdir
mkdir -p testdir
mkdir -p testdata/1
mkdir -p testdata/1/empty
mkdir -p testdata/1/notempty
echo "testtestasdf" > testdata/1/notempty/testfile
dd if=/dev/urandom of=testdata/1/a bs=1M count=$TESTSIZE
dd if=/dev/urandom of=testdata/1/b bs=1M count=$TESTSIZE
dd if=/dev/urandom of=testdata/1/c bs=1M count=$TESTSIZE
ln -s a testdata/1/l
ln -s aa testdata/1/aa
cp -a -p testdata/1 testdata/2
echo "asdf1" > testdata/2/c
cat testdata/1/c >> testdata/2/c
sleep 1
cp -a -p testdata/2 testdata/3
echo "asdf2" > testdata/3/a
cat testdata/2/a >> testdata/3/a
rm testdata/3/l
ln -s b testdata/3/l
cp -a -p testdata/3 testdata/4
echo "asdf3" > testdata/4/b
cat testdata/3/b >> testdata/4/b
cp -a -p testdata/1 testdata/5
cp -a -p testdata/1 testdata/6
rm testdata/6/a
cp -a -p testdata/1 testdata/7
cp -a -p testdata/7 testdata/8
echo "asdf3" > testdata/8/b
cat testdata/7/b >> testdata/8/b
echo "Data created"
if ! $CMD init --repo testdir/to1 --compression zlib --compression-level 4 --encryption aes --password asdff --salt e --full-period 999; then
echo "Error creating repo!"
exit 1
fi
echo "Repo created"
OUT=$($CMD run --from testdata/1 --repo testdir/to1 --password asdff --progress simple --verbose 1)
echo "$OUT"
if ! ( ( echo "$OUT" | grep -q 'Copied: a' ) && ( echo "$OUT" | grep -q 'Copied: aa' ) && ( echo "$OUT" | grep -q 'Copied: b' ) && ( echo "$OUT" | grep -q 'Copied: c' ) ); then
echo "Error backing up 1 dir!"
exit 1
fi
echo "Backup 1 ok"
OUT=$($CMD run --from testdata/2 --repo testdir/to1 --password asdff --progress simple --verbose 1)
echo "$OUT"
if ! ( ( echo "$OUT" | grep -q 'Skipped: a' ) && ( echo "$OUT" | grep -q 'Skipped: b' ) && ( echo "$OUT" | grep -q 'Skipped: aa' ) &&\
( echo "$OUT" | grep -q 'Skipped: empty' ) && ( echo "$OUT" | grep -q 'Skipped: l' ) && ( echo "$OUT" | grep -q 'Skipped: notempty' ) && ( echo "$OUT" | grep -q 'Copied: c' ) ); then
echo "Error backing up 2 dir!"
exit 1
fi
echo "Backup 2 ok"
OUT=$($CMD run --from testdata/3 --repo testdir/to1 --password asdff --progress simple --verbose 1)
echo "$OUT"
if ! ( ( echo "$OUT" | grep -q 'Copied: a' ) && ( echo "$OUT" | grep -q 'Copied: l' ) && ( echo "$OUT" | grep -q 'Skipped: b' ) &&\
( echo "$OUT" | grep -q 'Skipped: empty' ) && ( echo "$OUT" | grep -q 'Skipped: notempty' ) && ( echo "$OUT" | grep -q 'Skipped: c' ) ); then
echo "$OUT"
echo "Error backing up 3 dir!"
exit 1
fi
echo "Backup 3 ok"
OUT=$($CMD run --from testdata/4 --repo testdir/to1 --password asdff --progress simple --verbose 1)
echo "$OUT"
if ! ( ( echo "$OUT" | grep -q 'Skipped: a' ) && ( echo "$OUT" | grep -q 'Skipped: aa' ) && ( echo "$OUT" | grep -q 'Copied: b' ) && ( echo "$OUT" | grep -q 'Skipped: c' ) ); then
echo "Error backing up 4 dir!"
exit 1
fi
echo "Backup 4 ok"
OUT=$($CMD run --from testdata/5 --repo testdir/to1 --password asdff --progress simple --verbose 1)
echo "$OUT"
if ! ( ( echo "$OUT" | grep -q 'Copied: a' ) && ( echo "$OUT" | grep -q 'Copied: b' ) && ( echo "$OUT" | grep -q 'Copied: c' ) ); then
echo "Error backing up 5 dir!"
exit 1
fi
echo "Backup 5 ok"
OUT=$($CMD run --from testdata/6 --repo testdir/to1 --password asdff --progress simple --verbose 1)
echo "$OUT"
if ! ( ! ( echo "$OUT" | grep -q 'Copied: a' ) && ! ( echo "$OUT" | grep -q 'Skipped: a ' ) && ( echo "$OUT" | grep -q 'Skipped: aa' ) && ( echo "$OUT" | grep -q 'Skipped: b' ) && ( echo "$OUT" | grep -q 'Skipped: c' ) ); then
echo "Error backing up 6 dir!"
exit 1
fi
echo "Backup 6 ok"
OUT=$($CMD run --from testdata/7 --repo testdir/to1 --password asdff --progress simple --verbose 1)
echo "$OUT"
if ! ( ( echo "$OUT" | grep -q 'Copied: a' ) && ( echo "$OUT" | grep -q 'Skipped: aa' ) && ( echo "$OUT" | grep -q 'Skipped: b' ) && ( echo "$OUT" | grep -q 'Skipped: c' ) ); then
echo "Error backing up 7 dir!"
exit 1
fi
echo "Backup 7 ok"
i=$((0))
AIDS=()
OUT=$($CMD list --repo testdir/to1 --password asdff)
echo "$OUT"
while IFS= read -r l; do
((i++))
aid=$(echo $l | grep -Eo '[0-9]+' | tail -1)
AIDS+=("$aid")
$CMD restore --repo testdir/to1 --password asdff --aid $aid --to testdir/res$((i))
if ! diff --no-dereference -r testdata/$((i)) testdir/res$((i)); then
echo "Archive not restored properly!"
exit 1
fi
echo "Restore $((i)) OK"
done <<< "$OUT"
OUT=$($CMD diff --from testdata/4 --repo testdir/to1 --password asdff --progress none --verbose 1 --aid ${AIDS[0]} --aid2 ${AIDS[1]})
echo "$OUT"
if ! ( ( echo "$OUT" | grep -q 'c is different' ) && ! ( echo "$OUT" | grep -q 'a is different' ) && ! ( echo "$OUT" | grep -q 'l is different' )\
&& ! ( echo "$OUT" | grep -q 'aa is different' ) && ! ( echo "$OUT" | grep -q 'b is different' ) && ! ( echo "$OUT" | grep -q 'empty is different' ) && ! ( echo "$OUT" | grep -q 'notempty is different' ) ); then
echo "Error comparing archive 1 and 2!"
exit 1
fi
echo "OK comparing archive 1 and 2"
OUT=$($CMD diff --from testdata/4 --repo testdir/to1 --password asdff --progress none --verbose 1 --aid ${AIDS[1]} --aid2 ${AIDS[2]})
echo "$OUT"
if ! ( ( echo "$OUT" | grep -q 'a is different' ) && ( echo "$OUT" | grep -q 'l is different' ) && ! ( echo "$OUT" | grep -q 'c is different' ) \
&& ! ( echo "$OUT" | grep -q 'b is different' ) && ! ( echo "$OUT" | grep -q 'empty is different' ) && ! ( echo "$OUT" | grep -q 'notempty is different' ) ); then
echo "Error comparing archive 2 and 3!"
exit 1
fi
echo "OK comparing archive 2 and 3"
OUT=$($CMD diff --diff-mode file --from testdata/4 --prefix a --repo testdir/to1 --password asdff --progress none --verbose 1 --aid ${AIDS[1]} --aid2 ${AIDS[2]})
echo "$OUT"
if ! ( ( echo "$OUT" | grep -q 'a is different' ) && ! ( echo "$OUT" | grep -q 'l is different' ) ); then
echo "Error comparing archive 2 and 3! (file 1)"
exit 1
fi
echo "OK comparing archive 2 and 3 (file 1)"
OUT=$($CMD diff --diff-mode file --from testdata/4 --prefix l --repo testdir/to1 --password asdff --progress none --verbose 1 --aid ${AIDS[1]} --aid2 ${AIDS[2]})
echo "$OUT"
if ! ( ! ( echo "$OUT" | grep -q 'a is different' ) && ( echo "$OUT" | grep -q 'l is different' ) ); then
echo "Error comparing archive 2 and 3! (file 2)"
exit 1
fi
echo "OK comparing archive 2 and 3 (file 2)"
OUT=$($CMD diff --diff-mode file --from testdata/4 --prefix b --repo testdir/to1 --password asdff --progress none --verbose 1 --aid ${AIDS[1]} --aid2 ${AIDS[2]})
echo "$OUT"
if ! ( ! ( echo "$OUT" | grep -q 'a is different' ) && ! ( echo "$OUT" | grep -q 'l is different' ) && ( echo "$OUT" | grep -q 'b are same' ) ); then
echo "Error comparing archive 2 and 3! (file 3)"
exit 1
fi
echo "OK comparing archive 2 and 3 (file 3)"
OUT=$($CMD diff --from testdata/4 --repo testdir/to1 --password asdff --progress none --verbose 1 --aid ${AIDS[2]})
echo "$OUT"
if ! ( ( echo "$OUT" | grep -q 'b is different' ) && ! ( echo "$OUT" | grep -q 'a is different' ) && ! ( echo "$OUT" | grep -q 'l is different' ) \
&& ! ( echo "$OUT" | grep -q 'aa is different' ) && ! ( echo "$OUT" | grep -q 'c is different' ) && ! ( echo "$OUT" | grep -q 'empty is different' ) && ! ( echo "$OUT" | grep -q 'notempty is different' ) ); then
echo "Error comparing archive 3 and current!"
exit 1
fi
echo "OK comparing archive 3 and current"
OUT=$($CMD diff --from testdata/3 --repo testdir/to1 --password asdff --progress none --verbose 1 )
echo "$OUT"
if ! ( ! ( echo "$OUT" | grep -q 'b is different' ) && ( echo "$OUT" | grep -q 'a is different' ) && ( echo "$OUT" | grep -q 'l is different' )\
&& ! ( echo "$OUT" | grep -q 'aa is different' ) && ( echo "$OUT" | grep -q 'c is different' ) && ! ( echo "$OUT" | grep -q 'empty is different' ) && ! ( echo "$OUT" | grep -q 'notempty is different' ) ); then
echo "Error comparing archive last and current!"
exit 1
fi
echo "OK comparing archive last and current"
if ! $CMD init --repo testdir/to2 --compression zlib --compression-level 4 --encryption aes --password asdff --salt e; then
echo "Error creating repo!"
exit 1
fi
echo "Repo created"
OUT=$($CMD run --from testdata/1 --repo testdir/to2 --password asdff --progress simple --verbose 1)
echo "$OUT"
if ! ( (echo "$OUT" | grep -q 'Backup is full because there are no backups')&&( echo "$OUT" | grep -q 'Copied: a' ) && ( echo "$OUT" | grep -q 'Copied: aa' ) && ( echo "$OUT" | grep -q 'Copied: b' ) && ( echo "$OUT" | grep -q 'Copied: c' ) ); then
echo "Error backing up 1 dir!"
exit 1
fi
echo "Backup 1 ok"
OUT=$($CMD run --from testdata/1 --repo testdir/to2 --password asdff --progress simple --verbose 1)
echo "$OUT"
if ! ( ! ( echo "$OUT" | grep -q 'Backup is full' ) && ( echo "$OUT" | grep -q 'Skipped: a' ) && ( echo "$OUT" | grep -q 'Skipped: aa' ) && ( echo "$OUT" | grep -q 'Skipped: b' ) && ( echo "$OUT" | grep -q 'Skipped: c' )); then
echo "Error backing up 2 dir!"
exit 1
fi
echo "Backup 2 ok"
OUT=$($CMD run --from testdata/1 --repo testdir/to2 --password asdff --progress simple --verbose 1)
echo "$OUT"
if ! ( ! ( echo "$OUT" | grep -q 'Backup is full' )&& ( echo "$OUT" | grep -q 'Skipped: a' ) && ( echo "$OUT" | grep -q 'Skipped: aa' ) && ( echo "$OUT" | grep -q 'Skipped: b' ) && ( echo "$OUT" | grep -q 'Skipped: c' ) ); then
echo "Error backing up 3 dir!"
exit 1
fi
echo "Backup 3 ok"
OUT=$($CMD run --from testdata/1 --repo testdir/to2 --password asdff --progress simple --verbose 1)
echo "$OUT"
if ! ( ( echo "$OUT" | grep -q 'Backup is full because of the interval') &&( echo "$OUT" | grep -q 'Copied: a' ) && ( echo "$OUT" | grep -q 'Copied: aa' ) && ( echo "$OUT" | grep -q 'Copied: b' ) && ( echo "$OUT" | grep -q 'Copied: c' )); then
echo "Error backing up 4 dir!"
exit 1
fi
echo "Backup 4 ok"
OUT=$($CMD run --from testdata/1 --repo testdir/to2 --password asdff --progress simple --verbose 1)
echo "$OUT"
if ! ( ! ( echo "$OUT" | grep -q 'Backup is full' ) && ( echo "$OUT" | grep -q 'Skipped: a' ) && ( echo "$OUT" | grep -q 'Skipped: aa' ) && ( echo "$OUT" | grep -q 'Skipped: b' ) && ( echo "$OUT" | grep -q 'Skipped: c' ) ); then
echo "Error backing up 5 dir!"
exit 1
fi
echo "Backup 5 ok"
OUT=$($CMD run --from testdata/1 --repo testdir/to2 --password asdff --progress simple --verbose 1)
echo "$OUT"
if ! ( ! ( echo "$OUT" | grep -q 'Backup is full' ) && ( echo "$OUT" | grep -q 'Skipped: a' ) && ( echo "$OUT" | grep -q 'Skipped: aa' ) && ( echo "$OUT" | grep -q 'Skipped: b' ) && ( echo "$OUT" | grep -q 'Skipped: c' ) ); then
echo "Error backing up 6 dir!"
exit 1
fi
echo "Backup 6 ok"
OUT=$($CMD run --from testdata/1 --repo testdir/to2 --password asdff --progress simple --verbose 1)
echo "$OUT"
if ! ( ( echo "$OUT" | grep -q 'Backup is full because of the interval' ) &&( echo "$OUT" | grep -q 'Copied: a' ) && ( echo "$OUT" | grep -q 'Copied: aa' ) && ( echo "$OUT" | grep -q 'Copied: b' ) && ( echo "$OUT" | grep -q 'Copied: c' ) ); then
echo "Error backing up 7 dir!"
exit 1
fi
echo "Backup 7 ok"
OUT=$($CMD run --from testdata/1 --repo testdir/to2 --password asdff --progress simple --verbose 1 --type full)
echo "$OUT"
if ! ( ( echo "$OUT" | grep -q 'Backup is full because of the config') &&( echo "$OUT" | grep -q 'Copied: a' ) && ( echo "$OUT" | grep -q 'Copied: aa' ) && ( echo "$OUT" | grep -q 'Copied: b' ) && ( echo "$OUT" | grep -q 'Copied: c' )); then
echo "Error backing up 8 dir!"
exit 1
fi
echo "Backup 8 ok"
OUT=$($CMD run --from testdata/1 --repo testdir/to2 --password asdff --progress simple --verbose 1)
echo "$OUT"
if ! ( ! ( echo "$OUT" | grep -q 'Backup is full' ) && ( echo "$OUT" | grep -q 'Skipped: a' ) && ( echo "$OUT" | grep -q 'Skipped: aa' ) && ( echo "$OUT" | grep -q 'Skipped: b' ) && ( echo "$OUT" | grep -q 'Skipped: c' ) ); then
echo "Error backing up 9 dir!"
exit 1
fi
echo "Backup 9 ok"
OUT=$($CMD run --from testdata/1 --repo testdir/to2 --password asdff --progress simple --verbose 1)
echo "$OUT"
if ! ( ! ( echo "$OUT" | grep -q 'Backup is full' ) && ( echo "$OUT" | grep -q 'Skipped: a' ) && ( echo "$OUT" | grep -q 'Skipped: aa' ) && ( echo "$OUT" | grep -q 'Skipped: b' ) && ( echo "$OUT" | grep -q 'Skipped: c' ) ); then
echo "Error backing up 10 dir!"
exit 1
fi
echo "Backup 10 ok"
OUT=$($CMD run --from testdata/1 --repo testdir/to2 --password asdff --progress simple --verbose 1)
echo "$OUT"
if ! ( ( echo "$OUT" | grep -q 'Backup is full because of the interval' ) &&( echo "$OUT" | grep -q 'Copied: a' ) && ( echo "$OUT" | grep -q 'Copied: aa' ) && ( echo "$OUT" | grep -q 'Copied: b' ) && ( echo "$OUT" | grep -q 'Copied: c' ) ); then
echo "Error backing up 11 dir!"
exit 1
fi
echo "Backup 11 ok"
rm -rf testdata
rm -rf testdir
exit 0

182
tests/clitests/diff.sh Executable file
View File

@@ -0,0 +1,182 @@
#!/bin/bash
CMD=./sembackup
rm -rf testdata
rm -rf testdir
mkdir -p testdir
mkdir -p testdata/1
mkdir -p testdata/1/empty
mkdir -p testdata/1/notempty
mkdir -p testdata/1/emptyi
mkdir -p testdata/1/notemptyi
mkdir -p testdata/1/notempty2/empty
mkdir -p testdata/1/notempty2/notemptyi2
mkdir -p testdata/1/notempty2/notemptyi2/ignoredir
echo "testtestasdf1" > testdata/1/notempty/testfile
echo "testtestasdf2" > testdata/1/notemptyi/testfile
echo "testtestasdf3" > testdata/1/notempty2/notempty
echo "testtestasdf4" > testdata/1/notempty2/notemptyi2/test4
echo "testtestasdf5" > testdata/1/notempty2/notemptyi2/test5
echo "testtestasdf6" > testdata/1/notempty2/notemptyi2/test6
echo "testtestasdf7" > testdata/1/notempty2/notemptyi2/test7
echo "testtestasdf8" > testdata/1/notempty2/notemptyi2/ignoredir/testa
echo "testtestasdf9" > testdata/1/filexd
echo ".*4" > testdata/1/notempty2/.ignore
echo ".*5" > testdata/1/notempty2/notemptyi2/.ignore
touch testdata/1/notemptyi/.nobackup
touch testdata/1/emptyi/.nobackup
touch testdata/1/notempty2/notemptyi2/ignoredir/.nobackup
cp -a -p testdata/1 testdata/2
echo "testtestasdf4u" > testdata/2/notempty2/notemptyi2/test4
echo "testtestasdf5u" > testdata/2/notempty2/notemptyi2/test5
echo "testtestasdf6u" > testdata/2/notempty2/notemptyi2/test6
echo "testtestasdf7u" > testdata/2/notempty2/notemptyi2/test7
echo "testtestasdf8u" > testdata/2/notempty2/notemptyi2/ignoredir/testa
echo "testtestasdf9u" > testdata/2/filexd
cp -a -p testdata/2 testdata/3
echo "testtestasdf4uu" > testdata/3/notempty2/notemptyi2/test4
echo "testtestasdf5uu" > testdata/3/notempty2/notemptyi2/test5
echo "testtestasdf6uu" > testdata/3/notempty2/notemptyi2/test6
echo "testtestasdf7uu" > testdata/3/notempty2/notemptyi2/test7
echo "testtestasdf8uu" > testdata/3/notempty2/notemptyi2/ignoredir/testa
echo "testtestasdf9uu" > testdata/3/filexd
cp -a -p testdata/2 testdata/4
echo "testtestasdf4uuu" > testdata/4/notempty2/notemptyi2/test4
echo "testtestasdf5uuu" > testdata/4/notempty2/notemptyi2/test5
echo "testtestasdf6uuu" > testdata/4/notempty2/notemptyi2/test6
echo "testtestasdf7uuu" > testdata/4/notempty2/notemptyi2/test7
echo "testtestasdf8uuu" > testdata/4/notempty2/notemptyi2/ignoredir/testa
echo "testtestasdf9uuu" > testdata/4/filexd
echo "Data created"
if ! $CMD init --repo testdir/to1 --compression zlib --compression-level 4 --encryption aes --password asdff --salt e --full-period 999; then
echo "Error creating repo!"
exit 1
fi
echo "Repo created"
OUT=$($CMD run --from testdata/1 --repo testdir/to1 --password asdff --progress simple --verbose 1)
echo "$OUT"
if ! ( ( echo "$OUT" | grep -q 'Copied: notempty/testfile' )\
&& ( echo "$OUT" | grep -q 'Copied: notempty' )\
&& ( echo "$OUT" | grep -q 'Copied: notempty2' )\
&& ( echo "$OUT" | grep -q 'Copied: notempty2/notempty' ) \
&& ( echo "$OUT" | grep -q 'Copied: filexd' ) \
&& ! ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test4 ' )\
&& ! ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test5 ' )\
&& ! ( echo "$OUT" | grep -q 'notemptyi ' )\
&& ! ( echo "$OUT" | grep -q 'emptyi ' )\
&& ! ( echo "$OUT" | grep -q 'notemptyi/testfile' )\
&& ! ( echo "$OUT" | grep -q 'notemptyi2/ignoredir/testa' )\
&& ( echo "$OUT" | grep -q 'Copied: notempty2/notemptyi2/test6' )\
&& ( echo "$OUT" | grep -q 'Copied: notempty2/notemptyi2/test7' ) ); then
echo "Error backing up 1 dir!"
exit 1
fi
echo "Backup 1 ok"
OUT=$($CMD run --from testdata/2 --repo testdir/to1 --password asdff --progress simple --verbose 1)
echo "$OUT"
if ! ( ! ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test4 ' )\
&& ! ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test5 ' )\
&& ! ( echo "$OUT" | grep -q 'notemptyi2/ignoredir/testa ' )\
&& ( echo "$OUT" | grep -q 'Copied: filexd' ) \
&& ( echo "$OUT" | grep -q 'Copied: notempty2/notemptyi2/test6' )\
&& ( echo "$OUT" | grep -q 'Copied: notempty2/notemptyi2/test7' ) ); then
echo "Error backing up 2 dir!"
exit 1
fi
echo "Backup 2 ok"
OUT=$($CMD run --from testdata/3 --repo testdir/to1 --password asdff --progress simple --verbose 1)
echo "$OUT"
if ! ( ! ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test4 ' )\
&& ! ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test5 ' )\
&& ! ( echo "$OUT" | grep -q 'notemptyi2/ignoredir/testa ' )\
&& ( echo "$OUT" | grep -q 'Copied: filexd' ) \
&& ( echo "$OUT" | grep -q 'Copied: notempty2/notemptyi2/test6' )\
&& ( echo "$OUT" | grep -q 'Copied: notempty2/notemptyi2/test7' ) ); then
echo "Error backing up 3 dir!"
exit 1
fi
echo "Backup 3 ok"
i=$((0))
AIDS=()
OUT=$($CMD list --repo testdir/to1 --password asdff)
echo "$OUT"
while IFS= read -r l; do
((i++))
aid=$(echo $l | grep -Eo '[0-9]+' | tail -1)
AIDS+=("$aid")
done <<< "$OUT"
OUT=$($CMD diff --from testdata/4 --repo testdir/to1 --password asdff --progress none --verbose 1 --aid ${AIDS[0]} --aid2 ${AIDS[1]})
echo "$OUT"
if ! ( ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test6 is different' ) && ( echo "$OUT" | grep -q 'filexd is different' ) && ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test7 is different' ) \
&& ! ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test4' ) && ! ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test5' ) && ! ( echo "$OUT" | grep -q 'notemptyi2/ignoredir/testa' ) ); then
echo "Error comparing archive 1 and 2!"
exit 1
fi
echo "OK comparing archive 1 and 2"
OUT=$($CMD diff --from testdata/4 --repo testdir/to1 --password asdff --progress none --verbose 1 --aid ${AIDS[1]} --aid2 ${AIDS[2]})
echo "$OUT"
if ! ( ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test6 is different' ) && ( echo "$OUT" | grep -q 'filexd is different' ) && ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test7 is different' ) \
&& ! ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test4' ) && ! ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test5' ) && ! ( echo "$OUT" | grep -q 'notemptyi2/ignoredir/testa' ) ); then
echo "Error comparing archive 2 and 3!"
exit 1
fi
echo "OK comparing archive 2 and 3"
OUT=$($CMD diff --from testdata/4 --repo testdir/to1 --password asdff --progress none --verbose 1 --aid ${AIDS[2]})
echo "$OUT"
if ! ( ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test6 is different' ) && ( echo "$OUT" | grep -q 'filexd is different' ) && ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test7 is different' ) \
&& ! ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test4' ) && ! ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test5' ) && ! ( echo "$OUT" | grep -q 'notemptyi2/ignoredir/testa' ) ); then
echo "Error comparing archive 3 and current!"
exit 1
fi
echo "OK comparing archive 3 and current"
OUT=$($CMD diff --from testdata/4 --repo testdir/to1 --password asdff --progress none --verbose 1 )
echo "$OUT"
if ! ( ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test6 is different' ) && ( echo "$OUT" | grep -q 'filexd is different' ) && ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test7 is different' ) \
&& ! ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test4' ) && ! ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test5' ) && ! ( echo "$OUT" | grep -q 'notemptyi2/ignoredir/testa' ) ); then
echo "Error comparing archive last (3) and current!"
exit 1
fi
echo "OK comparing archive last (3) and current"
OUT=$($CMD diff --from testdata/4 --repo testdir/to1 --password asdff --progress none --verbose 1 --aid ${AIDS[2]} --prefix notempty2/notemptyi2 )
echo "$OUT"
if ! ( ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test6 is different' ) && ! ( echo "$OUT" | grep -q 'filexd is different' ) && ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test7 is different' ) \
&& ! ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test4' ) && ! ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test5' ) && ! ( echo "$OUT" | grep -q 'notemptyi2/ignoredir/testa' ) ); then
echo "Error comparing archive 3 and current!"
exit 1
fi
echo "OK comparing archive 3 and current with prefix "
OUT=$($CMD diff --from testdata/4 --repo testdir/to1 --password asdff --progress none --verbose 1 --prefix notempty2/notemptyi2 )
echo "$OUT"
if ! ( ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test6 is different' ) && ! ( echo "$OUT" | grep -q 'filexd is different' ) && ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test7 is different' ) \
&& ! ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test4' ) && ! ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test5' ) && ! ( echo "$OUT" | grep -q 'notemptyi2/ignoredir/testa' ) ); then
echo "Error comparing archive last (3) and current!"
exit 1
fi
echo "OK comparing archive last (3) and current with prefix "
rm -rf testdata
rm -rf testdir
exit 0

89
tests/clitests/ignore.sh Executable file
View File

@@ -0,0 +1,89 @@
#!/bin/bash
CMD=./sembackup
rm -rf testdata
rm -rf testdir
mkdir -p testdir
mkdir -p testdata/1
mkdir -p testdata/1/empty
mkdir -p testdata/1/notempty
mkdir -p testdata/1/emptyi
mkdir -p testdata/1/notemptyi
mkdir -p testdata/1/notempty2/empty
mkdir -p testdata/1/notempty2/notemptyi2
echo "testtestasdf1" > testdata/1/notempty/testfile
echo "testtestasdf2" > testdata/1/notemptyi/testfile
echo "testtestasdf3" > testdata/1/notempty2/notempty
echo "testtestasdf4" > testdata/1/notempty2/notemptyi2/test4
echo "testtestasdf5" > testdata/1/notempty2/notemptyi2/test5
echo "testtestasdf6" > testdata/1/notempty2/notemptyi2/test6
echo "testtestasdf7" > testdata/1/notempty2/notemptyi2/test7
echo ".*4" > testdata/1/notempty2/.ignore
echo ".*5" > testdata/1/notempty2/notemptyi2/.ignore
touch testdata/1/notemptyi/.nobackup
touch testdata/1/emptyi/.nobackup
echo "Data created"
if ! $CMD init --repo testdir/to1 --compression zlib --compression-level 4 --encryption aes --password asdff --salt e --full-period 999; then
echo "Error creating repo!"
exit 1
fi
echo "Repo created"
OUT=$($CMD run --from testdata/1 --repo testdir/to1 --password asdff --progress simple --verbose 1)
echo "$OUT"
if ! ( ( echo "$OUT" | grep -q 'Copied: notempty/testfile' )\
&& ( echo "$OUT" | grep -q 'Copied: notempty' )\
&& ( echo "$OUT" | grep -q 'Copied: notempty2' )\
&& ( echo "$OUT" | grep -q 'Copied: notempty2/notempty' ) \
&& ! ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test4 ' )\
&& ! ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test5 ' )\
&& ! ( echo "$OUT" | grep -q 'notemptyi ' )\
&& ! ( echo "$OUT" | grep -q 'emptyi ' )\
&& ! ( echo "$OUT" | grep -q 'notemptyi/testfile' )\
&& ( echo "$OUT" | grep -q 'Copied: notempty2/notemptyi2/test6' )\
&& ( echo "$OUT" | grep -q 'Copied: notempty2/notemptyi2/test7' ) ); then
echo "Error backing up 1 dir!"
exit 1
fi
echo "Backup 1 ok"
i=$((0))
AIDS=()
OUT=$($CMD list --repo testdir/to1 --password asdff)
echo "$OUT"
while IFS= read -r l; do
((i++))
aid=$(echo $l | grep -Eo '[0-9]+' | tail -1)
AIDS+=("$aid")
done <<< "$OUT"
OUT=$($CMD list-files --aid ${AIDS[0]} --from testdata/1 --repo testdir/to1 --password asdff --progress simple --verbose 1)
echo "$OUT"
if ! ( ( echo "$OUT" | grep -q ' notempty/testfile' )\
&& ( echo "$OUT" | grep -q ' notempty' )\
&& ( echo "$OUT" | grep -q ' notempty2' )\
&& ( echo "$OUT" | grep -q ' notempty2/notempty' ) \
&& ! ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test4 ' )\
&& ! ( echo "$OUT" | grep -q 'notempty2/notemptyi2/test5 ' )\
&& ! ( echo "$OUT" | grep -q 'notemptyi ' )\
&& ! ( echo "$OUT" | grep -q 'emptyi ' )\
&& ! ( echo "$OUT" | grep -q 'notemptyi/testfile' )\
&& ( echo "$OUT" | grep -q ' notempty2/notemptyi2/test6' )\
&& ( echo "$OUT" | grep -q ' notempty2/notemptyi2/test7' ) ); then
echo "Error listing 1 dir!"
exit 1
fi
echo "List 1 ok"
rm -rf testdata
rm -rf testdir
exit 0

40
tests/crypto/AESTest.cpp Normal file
View File

@@ -0,0 +1,40 @@
//
// Created by Stepan Usatiuk on 30.04.2023.
//
#include "AESTest.h"
#include "../../src/crypto/AES.h"
std::unique_ptr<TestGroup> AESTest::operator()() {
auto tg = std::make_unique<TestGroup>("AES tests");
tg->addTest(std::make_unique<Test>("Simple AESTest test", std::function<bool()>([]() {
std::string in = "hello1";
auto enc = AES::encrypt(std::vector<char>(in.begin(), in.end()), "p1", "e");
auto dec = AES::decrypt(enc, "p1", "e");
HelpfulAssert<std::string>()(in, std::string(dec.begin(), dec.end()));
in = "1234567890asdfg";
enc = AES::encrypt(std::vector<char>(in.begin(), in.end()), "p1", "e");
dec = AES::decrypt(enc, "p1", "e");
HelpfulAssert<std::string>()(in, std::string(dec.begin(), dec.end()));
in = "1234567890asdfgh";
enc = AES::encrypt(std::vector<char>(in.begin(), in.end()), "p1", "e");
dec = AES::decrypt(enc, "p1", "e");
HelpfulAssert<std::string>()(in, std::string(dec.begin(), dec.end()));
in = "1234567890asdfghe";
enc = AES::encrypt(std::vector<char>(in.begin(), in.end()), "p1", "e");
dec = AES::decrypt(enc, "p1", "e");
HelpfulAssert<std::string>()(in, std::string(dec.begin(), dec.end()));
in = "1234567890asdfgheq";
enc = AES::encrypt(std::vector<char>(in.begin(), in.end()), "p1", "e");
dec = AES::decrypt(enc, "p1", "e");
HelpfulAssert<std::string>()(in, std::string(dec.begin(), dec.end()));
return true;
})));
return tg;
}

16
tests/crypto/AESTest.h Normal file
View File

@@ -0,0 +1,16 @@
//
// Created by Stepan Usatiuk on 30.04.2023.
//
#ifndef SEMBACKUP_AESTEST_H
#define SEMBACKUP_AESTEST_H
#include "../utils/TestGroupGenerator.h"
class AESTest : public TestGroupGenerator {
public:
std::unique_ptr<TestGroup> operator()() override;
};
#endif//SEMBACKUP_AESTEST_H

25
tests/crypto/MD5Test.cpp Normal file
View File

@@ -0,0 +1,25 @@
//
// Created by Stepan Usatiuk on 15.04.2023.
//
#include "MD5Test.h"
std::unique_ptr<TestGroup> MD5Test::operator()() {
auto tg = std::make_unique<TestGroup>("MD5 tests");
tg->addTest(std::make_unique<Test>("Simple MD5 test", std::function<bool()>([]() {
std::vector<char> data{'h', 'e', 'l', 'l', 'o'};
std::array<unsigned char, 16> excepted{0x5d, 0x41, 0x40, 0x2a, 0xbc, 0x4b, 0x2a, 0x76, 0xb9, 0x71, 0x9d, 0x91, 0x10, 0x17, 0xc5, 0x92};
auto out = MD5::calculate(data);
HelpfulAssert<size_t>()(out.size(), 16);
for (int i = 0; i < out.size(); i++) {
HelpfulAssert<unsigned char>()(out[i], excepted[i]);
}
return true;
})));
return tg;
}

17
tests/crypto/MD5Test.h Normal file
View File

@@ -0,0 +1,17 @@
//
// Created by Stepan Usatiuk on 15.04.2023.
//
#ifndef SEMBACKUP_MD5TEST_H
#define SEMBACKUP_MD5TEST_H
#include "../../src/crypto/MD5.h"
#include "../utils/TestGroupGenerator.h"
class MD5Test : public TestGroupGenerator {
public:
std::unique_ptr<TestGroup> operator()() override;
};
#endif//SEMBACKUP_MD5TEST_H

View File

@@ -0,0 +1,418 @@
//
// Created by Stepan Usatiuk on 16.04.2023.
//
#include "FullTest.h"
#include "../../src/Logger.h"
#include "../../src/commands/CommandRestore.h"
#include "../../src/commands/CommandRun.h"
#include "../../src/repo/FileRepository.h"
#include "../utils/Cleaner.h"
#include <filesystem>
#include <functional>
#include <string>
void randomChange(std::string path) {
std::fstream s(path);
auto pos = rand() % 50;
s.seekp(pos, std::ios::beg);
char out = rand() % 254;
s.write(&out, 1);
}
std::unique_ptr<TestGroup> FullTest::operator()() {
auto tg = std::make_unique<TestGroup>("Full tests");
tg->addTest(std::make_unique<Test>("Simple backup/restore test", std::function<bool()>([]() {
Cleaner c({"testfrom", "testto", "testtores"});
int aid = -1;
{
std::filesystem::create_directories("testfrom");
for (int i = 0; i < 257; i++) {
std::ofstream o(std::filesystem::path("testfrom") / ("f" + std::to_string(i)), std::ios::binary | std::ios::out | std::ios::trunc);
for (int j = 0; j < i; j++) o.put(j % 256);
}
std::filesystem::create_directories("testfrom/testdir");
Config conf;
conf.add("repo", "testto").add("from", "testfrom");
auto repo = std::make_unique<FileRepository>(conf);
repo->init();
std::stringstream runnerout;
Logger logger(1, runnerout);
CommandRun run;
run.run(Context{&logger, repo.get()});
aid = repo->getObjects(Object::ObjectType::Archive).begin()->second;
}
{
Config conf;
conf.add("repo", "testto").add("aid", std::to_string(aid)).add("to", "testtores");
auto repo = std::make_unique<FileRepository>(conf);
repo->open();
std::stringstream runnerout;
Logger logger(1, runnerout);
CommandRestore cmd;
cmd.run(Context{&logger, repo.get()});
}
{
try {
HelpfulAssert<bool>()(std::filesystem::is_directory("testtores/testdir"), true);
} catch (...) {
std::cerr << "Empty directory doesn't exist!" << std::endl;
throw;
}
for (int i = 0; i < 257; i++) {
std::ifstream o(std::filesystem::path("testtores") / ("f" + std::to_string(i)), std::ios::binary | std::ios::in);
try {
HelpfulAssert<bool>()(o.is_open(), true);
for (int j = 0; j < i; j++) {
char c;
HelpfulAssert<bool>()(o.get(c).operator bool(), true);
HelpfulAssert<char>()(j % 256, c);
}
} catch (...) {
std::cerr << "Error comparing file " << i << std::endl;
throw;
}
}
}
return true;
})));
tg->addTest(std::make_unique<Test>("Simple backup/restore with ignore test", std::function<bool()>([]() {
Cleaner c({"testfrom", "testto", "testtores"});
int aid = -1;
{
std::filesystem::create_directories("testfrom");
for (int i = 0; i < 257; i++) {
std::ofstream o(std::filesystem::path("testfrom") / ("f" + std::to_string(i)), std::ios::binary | std::ios::out | std::ios::trunc);
for (int j = 0; j < i; j++) o.put(j % 256);
}
std::filesystem::create_directories("testfrom/testdir");
std::filesystem::create_directories("testfrom/testdir2/testdir3");
std::filesystem::create_directories("testfrom/testdir2/testdir4");
{
std::ofstream file("testfrom/testdir2/.ignore");
file << "hello.txt";
}
{
std::ofstream file("testfrom/testdir2/testdir3/.ignore");
file << ".*\\.txt";
}
{
std::ofstream file("testfrom/testdir2/hello.txt");
file << "hello";
}
{
std::ofstream file("testfrom/testdir2/testdir3/hello.txt");
file << "hello2";
}
{
std::ofstream file("testfrom/testdir2/testdir3/asdf.txt");
file << "asdf1";
}
{
std::ofstream file("testfrom/testdir2/testdir4/asdf.txt");
file << "asdf2";
}
Config conf;
conf.add("repo", "testto").add("from", "testfrom");
auto repo = std::make_unique<FileRepository>(conf);
repo->init();
std::stringstream runnerout;
Logger logger(1, runnerout);
CommandRun cmd;
cmd.run(Context{&logger, repo.get()});
aid = repo->getObjects(Object::ObjectType::Archive).begin()->second;
}
{
Config conf;
conf.add("repo", "testto").add("aid", std::to_string(aid)).add("to", "testtores");
auto repo = std::make_unique<FileRepository>(conf);
repo->open();
std::stringstream runnerout;
Logger logger(1, runnerout);
CommandRestore cmd;
cmd.run(Context{&logger, repo.get()});
}
{
HelpfulAssert<bool>()(std::filesystem::is_directory("testtores/testdir"), true);
for (int i = 0; i < 257; i++) {
std::ifstream o(std::filesystem::path("testtores") / ("f" + std::to_string(i)), std::ios::binary | std::ios::in);
HelpfulAssert<bool>()(o.is_open(), true);
for (int j = 0; j < i; j++) {
char c;
HelpfulAssert<bool>()(o.get(c).operator bool(), true);
HelpfulAssert<char>()(j % 256, c);
}
}
{
std::ifstream file("testtores/testdir2/.ignore");
std::string s;
file >> s;
HelpfulAssert<std::string>()(s, "hello.txt");
}
{
std::ifstream file("testtores/testdir2/testdir3/.ignore");
std::string s;
file >> s;
HelpfulAssert<std::string>()(s, ".*\\.txt");
}
{
std::ifstream file("testtores/testdir2/hello.txt");
HelpfulAssert<bool>()(!file, true);
}
{
std::ifstream file("testtores/testdir2/testdir3/hello.txt");
HelpfulAssert<bool>()(!file, true);
}
{
std::ifstream file("testtores/testdir2/testdir3/asdf.txt");
HelpfulAssert<bool>()(!file, true);
}
{
std::ifstream file("testtores/testdir2/testdir4/asdf.txt");
std::string s;
file >> s;
HelpfulAssert<std::string>()(s, "asdf2");
}
}
return true;
})));
tg->addTest(std::make_unique<Test>("Backup/restore test with compression", std::function<bool()>([]() {
Cleaner c({"testfrom", "testto", "testtores"});
int aid = -1;
{
std::filesystem::create_directories("testfrom");
for (int i = 0; i < 257; i++) {
std::ofstream o(std::filesystem::path("testfrom") / ("f" + std::to_string(i)), std::ios::binary | std::ios::out | std::ios::trunc);
for (int j = 0; j < i; j++) o.put(j % 256);
}
std::filesystem::create_directories("testfrom/testdir");
Config conf;
conf.add("repo", "testto").add("compression", "zlib").add("from", "testfrom");
auto repo = std::make_unique<FileRepository>(conf);
repo->init();
std::stringstream runnerout;
Logger logger(1, runnerout);
CommandRun cmd;
cmd.run(Context{&logger, repo.get()});
aid = repo->getObjects(Object::ObjectType::Archive).begin()->second;
}
{
Config conf;
conf.add("repo", "testto").add("aid", std::to_string(aid)).add("to", "testtores");
auto repo = std::make_unique<FileRepository>(conf);
repo->open();
std::stringstream runnerout;
Logger logger(1, runnerout);
CommandRestore cmd;
cmd.run(Context{&logger, repo.get()});
}
{
HelpfulAssert<bool>()(std::filesystem::is_directory("testtores/testdir"), true);
for (int i = 0; i < 257; i++) {
std::ifstream o(std::filesystem::path("testtores") / ("f" + std::to_string(i)), std::ios::binary | std::ios::in);
HelpfulAssert<bool>()(o.is_open(), true);
for (int j = 0; j < i; j++) {
char c;
HelpfulAssert<bool>()(o.get(c).operator bool(), true);
HelpfulAssert<char>()(j % 256, c);
}
}
}
return true;
})));
tg->addTest(std::make_unique<Test>("Backup/restore test with compression/encryption", std::function<bool()>([]() {
Cleaner c({"testfrom", "testto", "testtores"});
int aid = -1;
{
std::filesystem::create_directories("testfrom");
for (int i = 0; i < 257; i++) {
std::ofstream o(std::filesystem::path("testfrom") / ("f" + std::to_string(i)), std::ios::binary | std::ios::out | std::ios::trunc);
for (int j = 0; j < i; j++) o.put(j % 256);
}
std::filesystem::create_directories("testfrom/testdir");
Config conf;
conf.add("repo", "testto").add("compression", "zlib").add("from", "testfrom").add("encryption", "aes").add("password", "testp").add("salt", "tests");
auto repo = std::make_unique<FileRepository>(conf);
repo->init();
std::stringstream runnerout;
Logger logger(1, runnerout);
CommandRun cmd;
cmd.run(Context{&logger, repo.get()});
aid = repo->getObjects(Object::ObjectType::Archive).begin()->second;
}
{
Config conf;
conf.add("repo", "testto");
auto repo = std::make_unique<FileRepository>(conf);
bool ok = true;
try {
HelpfulAssert<bool>()(repo->open(), false);
ok = false;
} catch (...) {}
HelpfulAssert<bool>()(ok, true);
}
{
Config conf;
conf.add("repo", "testto").add("password", "testp").add("aid", std::to_string(aid)).add("to", "testtores");
auto repo = std::make_unique<FileRepository>(conf);
repo->open();
std::stringstream runnerout;
Logger logger(1, runnerout);
CommandRestore cmd;
cmd.run(Context{&logger, repo.get()});
}
{
HelpfulAssert<bool>()(std::filesystem::is_directory("testtores/testdir"), true);
for (int i = 0; i < 257; i++) {
std::ifstream o(std::filesystem::path("testtores") / ("f" + std::to_string(i)), std::ios::binary | std::ios::in);
HelpfulAssert<bool>()(o.is_open(), true);
for (int j = 0; j < i; j++) {
char c;
HelpfulAssert<bool>()(o.get(c).operator bool(), true);
HelpfulAssert<char>()(j % 256, c);
}
}
}
return true;
})));
tg->addTest(std::make_unique<Test>("Repo data fuzz test", std::function<bool()>([]() {
srand(time(nullptr));
std::vector<Config> confs;
Config conf;
conf.add("repo", "testto").add("compression", "none").add("from", "testfrom").add("encryption", "none").add("password", "testp").add("salt", "tests").add("progress", "none");
confs.emplace_back(conf);
conf = Config();
conf.add("repo", "testto").add("compression", "zlib").add("from", "testfrom").add("encryption", "none").add("password", "testp").add("salt", "tests").add("progress", "none");
confs.emplace_back(conf);
conf = Config();
conf.add("repo", "testto").add("compression", "none").add("from", "testfrom").add("encryption", "zlib").add("password", "testp").add("salt", "tests").add("progress", "none");
confs.emplace_back(conf);
conf = Config();
conf.add("repo", "testto").add("compression", "zlib").add("from", "testfrom").add("encryption", "aes").add("password", "testp").add("salt", "tests").add("progress", "none");
confs.emplace_back(conf);
for (auto const &conf: confs) {
for (uint8_t filetobreak = 1; filetobreak <= 15; filetobreak++) {
std::cout << static_cast<int>(filetobreak) << " / 15 tests done" << std::endl;
for (uint8_t cutoff = 1; cutoff < 20; cutoff++) {
Cleaner c({"testfrom", "testto", "testtores"});
int aid = -1;
{
std::filesystem::create_directories("testfrom");
for (int i = 0; i < 2; i++) {
std::ofstream o(std::filesystem::path("testfrom") / ("f" + std::to_string(i)), std::ios::binary | std::ios::out | std::ios::trunc);
for (int j = 0; j < i; j++) o.put(j % 2);
}
auto repo = std::make_unique<FileRepository>(conf);
repo->init();
std::stringstream runnerout;
Logger logger(1, runnerout);
CommandRun cmd;
cmd.run(Context{&logger, repo.get()});
aid = repo->getObjects(Object::ObjectType::Archive).begin()->second;
}
{
if (filetobreak & 0b00000001) {
for (int i = 0; i < cutoff; i++)
randomChange("testto/1");
if (cutoff > 5)
std::filesystem::resize_file("testto/1", std::filesystem::file_size("testto/1") - cutoff);
}
if (filetobreak & 0b00000010) {
for (int i = 0; i < cutoff; i++)
randomChange("testto/index");
if (cutoff > 5)
std::filesystem::resize_file("testto/index", std::filesystem::file_size("testto/index") - cutoff);
}
if (filetobreak & 0b00000100) {
for (int i = 0; i < cutoff; i++)
randomChange("testto/offsets");
if (cutoff > 5)
std::filesystem::resize_file("testto/offsets", std::filesystem::file_size("testto/offsets") - cutoff);
}
if (filetobreak & 0b00001000) {
for (int i = 0; i < cutoff; i++)
randomChange("testto/info");
if (cutoff > 5)
std::filesystem::resize_file("testto/info", std::filesystem::file_size("testto/info") - cutoff);
}
}
{
bool ok = true;
try {
Config confr = conf;
confr.add("aid", std::to_string(aid)).add("to", "testtores");
auto repo = std::make_unique<FileRepository>(confr);
repo->open();
std::stringstream runnerout;
Logger logger(1, runnerout);
CommandRestore cmd;
cmd.run(Context{&logger, repo.get()});
auto outstr = runnerout.str();
if (outstr.find("Error") == std::string::npos)
ok = false;
} catch (...) {}
HelpfulAssert<bool>()(ok, true);
}
}
}
}
return true;
})));
return tg;
}

View File

@@ -0,0 +1,17 @@
//
// Created by Stepan Usatiuk on 16.04.2023.
//
#ifndef SEMBACKUP_FULLTEST_H
#define SEMBACKUP_FULLTEST_H
#include "../utils/TestGroupGenerator.h"
class FullTest : public TestGroupGenerator {
public:
std::unique_ptr<TestGroup> operator()() override;
};
#endif//SEMBACKUP_FULLTEST_H

113
tests/repo/ChunkTest.cpp Normal file
View File

@@ -0,0 +1,113 @@
//
// Created by Stepan Usatiuk on 14.04.2023.
//
#include "ChunkTest.h"
#include "../../src/repo/Serialize.h"
#include "../utils/Cleaner.h"
std::unique_ptr<TestGroup> ChunkTest::operator()() {
auto tg = std::make_unique<TestGroup>("Chunk tests");
tg->addTest(std::make_unique<Test>("De/serialize test", std::function<bool()>([]() {
std::vector<char> s1, s2;
{
std::vector<char> data1{'a', 'b', 'c', 'e'};
Chunk o1(666, {0}, data1);
std::vector<char> data2{'q', 'w', 'e', 'r', 'b'};
Chunk o2(777, {1}, data2);
s1 = Serialize::serialize(o1);
s2 = Serialize::serialize(o2);
}
{
auto s1b = s1.cbegin();
auto s2b = s2.cbegin();
Chunk o1(s1b, s1.cend()), o2(s2b, s2.cend());
std::vector<char> data1{'a', 'b', 'c', 'e'};
Chunk o1e(666, {0}, data1);
std::vector<char> data2{'q', 'w', 'e', 'r', 'b'};
Chunk o2e(777, {1}, data2);
HelpfulAssert<Object::idType>()(o1.id, o1e.id);
HelpfulAssert<Object::idType>()(o2.id, o2e.id);
HelpfulAssert<int>()((int) o1.type, (int) o1e.type);
HelpfulAssert<int>()((int) o2.type, (int) o2e.type);
HelpfulAssert<size_t>()(o1.data.size(), o1e.data.size());
HelpfulAssert<size_t>()(o2.data.size(), o2e.data.size());
for (int i = 0; i < o1.data.size(); i++) {
HelpfulAssert<char>()(o1.data[i], o1e.data[i]);
}
for (int i = 0; i < o2.data.size(); i++) {
HelpfulAssert<char>()(o2.data[i], o2e.data[i]);
}
for (int i = 0; i < o1.md5.size(); i++) {
HelpfulAssert<char>()(o1.md5[i], o1e.md5[i]);
}
for (int i = 0; i < o2.md5.size(); i++) {
HelpfulAssert<char>()(o2.md5[i], o2e.md5[i]);
}
}
return true;
})));
tg->addTest(std::make_unique<Test>("Garbage throw test", std::function<bool()>([]() {
std::vector<char> e{'a', 'b'};
auto eb = e.cbegin();
try {
Chunk o1(eb, e.cend());
} catch (...) {
return true;
}
throw Exception("Object constructed with garbage data!");
})));
tg->addTest(std::make_unique<Test>("Garbage throw test2", std::function<bool()>([]() {
std::vector<char> e{'s', 'e', 'm', 'b', 'a', 'a'};
auto eb = e.cbegin();
try {
Chunk o1(eb, e.cend());
} catch (...) {
return true;
}
throw Exception("Object constructed with garbage data!");
})));
tg->addTest(std::make_unique<Test>("Garbage throw test3", std::function<bool()>([]() {
std::vector<char> s1, s2;
{
std::vector<char> data1{'a', 'b', 'c', 'e'};
Chunk o1(666, {0}, data1);
std::vector<char> data2{'q', 'w', 'e', 'r', 'b'};
Chunk o2(777, {1}, data2);
s1 = Serialize::serialize(o1);
s2 = Serialize::serialize(o2);
}
{
s1.resize(s1.size() - 1);
s2.resize(s1.size() - 2);
bool fail = false;
try {
Chunk o1 = Serialize::deserialize<Chunk>(s1);
fail = true;
} catch (...) {
}
try {
Chunk o2 = Serialize::deserialize<Chunk>(s2);
fail = true;
} catch (...) {
}
if (fail)
throw Exception("Object constructed with garbage data!");
}
return true;
})));
return tg;
}

21
tests/repo/ChunkTest.h Normal file
View File

@@ -0,0 +1,21 @@
//
// Created by Stepan Usatiuk on 14.04.2023.
//
#ifndef SEMBACKUP_CHUNKTEST_H
#define SEMBACKUP_CHUNKTEST_H
#include <fstream>
#include <iostream>
#include <vector>
#include "../../src/repo/objects/Chunk.h"
#include "../utils/TestGroupGenerator.h"
class ChunkTest : public TestGroupGenerator {
public:
std::unique_ptr<TestGroup> operator()() override;
};
#endif//SEMBACKUP_CHUNKTEST_H

View File

@@ -0,0 +1,301 @@
//
// Created by Stepan Usatiuk on 14.04.2023.
//
#include "FileRepositoryTest.h"
std::unique_ptr<TestGroup> FileRepositoryTest::operator()() {
auto tg = std::make_unique<TestGroup>("FileRepository tests");
tg->addTest(std::make_unique<Test>("De/serialize test", std::function<bool()>([]() {
Cleaner c({"testrepo"});
{
Config conf;
conf.add("repo", "testrepo");
FileRepository repo(conf);
repo.init();
std::vector<char>
data1{'a', 'b', 'c', 'e'};
std::string o1k(16, '\0');
std::string o2k(16, '\0');
o2k[0] = 1;
o2k[1] = 2;
Chunk o1(666, o1k, data1);
std::vector<char> data2{'q', 'w', 'e', 'r', static_cast<char>(255)};
Chunk o2(777, o2k, data2);
repo.putObject(o1);
repo.putObject(o2);
HelpfulAssert<Object::idType>()(repo.getObjectId(Object::ObjectType::Chunk, o1k), 666);
HelpfulAssert<Object::idType>()(repo.getObjectId(Object::ObjectType::Chunk, o2k), 777);
}
{
Config conf;
conf.add("repo", "testrepo");
FileRepository repo(conf);
repo.open();
std::string o1k(16, '\0');
std::string o2k(16, '\0');
o2k[0] = 1;
o2k[1] = 2;
HelpfulAssert<Object::idType>()(repo.getObjectId(Object::ObjectType::Chunk, o1k), 666);
HelpfulAssert<Object::idType>()(repo.getObjectId(Object::ObjectType::Chunk, o2k), 777);
auto o1o = repo.getObject(666);
auto o2o = repo.getObject(777);
auto o1ob = o1o.cbegin();
auto o2ob = o2o.cbegin();
Chunk o1(o1ob, o1o.cend()), o2(o2ob, o2o.cend());
std::vector<char> data1{'a', 'b', 'c', 'e'};
Chunk o1e(666, o1k, data1);
std::vector<char> data2{'q', 'w', 'e', 'r', static_cast<char>(255)};
Chunk o2e(777, o2k, data2);
HelpfulAssert<Object::idType>()(o1.id, o1e.id);
HelpfulAssert<Object::idType>()(o2.id, o2e.id);
HelpfulAssert<int>()((int) o1.type, (int) o1e.type);
HelpfulAssert<int>()((int) o2.type, (int) o2e.type);
auto o1d = o1.data;
auto o1ed = o1e.data;
auto o2d = o2.data;
auto o2ed = o2e.data;
HelpfulAssert<size_t>()(o1.data.size(), o1e.data.size());
HelpfulAssert<size_t>()(o2.data.size(), o2e.data.size());
for (int i = 0; i < o1.data.size(); i++) {
HelpfulAssert<char>()(o1.data[i], o1e.data[i]);
}
for (int i = 0; i < o2.data.size(); i++) {
HelpfulAssert<char>()(o2.data[i], o2e.data[i]);
}
}
return true;
})));
tg->addTest(std::make_unique<Test>("De/serialize with sync/read filter", std::function<bool()>([]() {
Cleaner c({"testrepo"});
{
Config conf;
conf.add("repo", "testrepo")
.add("compression", "shiftC")
.add("compression-level", "1")
.add("encryption", "shiftE")
.add("password", "\a")
.add("salt", "a");
FileRepository repo(conf);
repo.init();
std::string o1k(16, '\0');
std::string o2k(16, '\0');
o2k[0] = 1;
o2k[1] = 2;
std::vector<char>
data1{'a', 'b', 'c', 'e'};
Chunk o1(666, o1k, data1);
std::vector<char> data2{'q', 'w', 'e', 'r', 'b'};
Chunk o2(777, o2k, data2);
repo.putObject(o1);
repo.putObject(o2);
HelpfulAssert<Object::idType>()(repo.getObjectId(Object::ObjectType::Chunk, o1k), 666);
HelpfulAssert<Object::idType>()(repo.getObjectId(Object::ObjectType::Chunk, o2k), 777);
}
{
Config conf;
conf.add("repo", "testrepo")
.add("compression", "shiftC")
.add("compression-level", "1")
.add("encryption", "shiftE")
.add("password", "\b")
.add("salt", "a");
FileRepository repo(conf);
bool err = false;
try {
repo.open();
err = true;
} catch (...) {}
try {
auto o1o = repo.getObject(666);
auto o1ob = o1o.cbegin();
Chunk o1(o1ob, o1o.cend());
err = true;
} catch (...) {}
try {
auto o2o = repo.getObject(777);
auto o2ob = o2o.cbegin();
Chunk o2(o2ob, o2o.cend());
err = true;
} catch (...) {}
if (err)
throw Exception("Object constructed with garbage data!");
}
{
Config conf;
conf.add("repo", "testrepo")
.add("compression", "shiftC")
.add("compression-level", "1")
.add("encryption", "shiftE")
.add("password", "\a")
.add("salt", "a");
FileRepository repo(conf);
repo.open();
std::string o1k(16, '\0');
std::string o2k(16, '\0');
o2k[0] = 1;
o2k[1] = 2;
HelpfulAssert<Object::idType>()(repo.getObjectId(Object::ObjectType::Chunk, o1k), 666);
HelpfulAssert<Object::idType>()(repo.getObjectId(Object::ObjectType::Chunk, o2k), 777);
auto o1o = repo.getObject(666);
auto o2o = repo.getObject(777);
auto o1ob = o1o.cbegin();
auto o2ob = o2o.cbegin();
Chunk o1(o1ob, o1o.cend()), o2(o2ob, o2o.cend());
std::vector<char> data1{'a', 'b', 'c', 'e'};
Chunk o1e(666, o1k, data1);
std::vector<char> data2{'q', 'w', 'e', 'r', 'b'};
Chunk o2e(777, o2k, data2);
HelpfulAssert<Object::idType>()(o1.id, o1e.id);
HelpfulAssert<Object::idType>()(o2.id, o2e.id);
HelpfulAssert<int>()((int) o1.type, (int) o1e.type);
HelpfulAssert<int>()((int) o2.type, (int) o2e.type);
auto o1d = o1.data;
auto o1ed = o1e.data;
auto o2d = o2.data;
auto o2ed = o2e.data;
HelpfulAssert<size_t>()(o1.data.size(), o1e.data.size());
HelpfulAssert<size_t>()(o2.data.size(), o2e.data.size());
for (int i = 0; i < o1.data.size(); i++) {
HelpfulAssert<char>()(o1.data[i], o1e.data[i]);
}
for (int i = 0; i < o2.data.size(); i++) {
HelpfulAssert<char>()(o2.data[i], o2e.data[i]);
}
}
return true;
})));
tg->addTest(std::make_unique<Test>("IDs test (disabled)", std::function<bool()>([]() {
return true;
Cleaner c({"testrepo"});
{
Config conf;
conf.add("repo", "testrepo");
FileRepository repo(conf);
repo.init();
std::string o1k(16, '\0');
std::string o2k(16, '\0');
o2k[0] = 1;
std::vector<char>
data1{'a', 'b', 'c', 'e'};
Chunk o1(repo.getId(), o1k, data1);
std::vector<char> data2{'q', 'w', 'e', 'r', 'b'};
Chunk o2(repo.getId(), o2k, data2);
HelpfulAssert<int>()(o1.id, 1);
HelpfulAssert<int>()(o2.id, 2);
repo.putObject(o1);
repo.putObject(o2);
HelpfulAssert<Object::idType>()(repo.getObjectId(Object::ObjectType::Chunk, o1k), 1);
HelpfulAssert<Object::idType>()(repo.getObjectId(Object::ObjectType::Chunk, o2k), 2);
}
{
Config conf;
conf.add("repo", "testrepo");
FileRepository repo(conf);
repo.open();
auto o1o = repo.getObject(1);
auto o2o = repo.getObject(2);
auto o1ob = o1o.cbegin();
auto o2ob = o2o.cbegin();
Chunk o1(o1ob, o1o.cend()), o2(o2ob, o2o.cend());
std::string o1k(16, '\0');
std::string o2k(16, '\0');
o2k[0] = 1;
std::vector<char> data1{'a', 'b', 'c', 'e'};
Chunk o1e(1, o1k, data1);
std::vector<char> data2{'q', 'w', 'e', 'r', 'b'};
Chunk o2e(2, o2k, data2);
HelpfulAssert<Object::idType>()(o1.id, o1e.id);
HelpfulAssert<Object::idType>()(o2.id, o2e.id);
HelpfulAssert<int>()((int) o1.type, (int) o1e.type);
HelpfulAssert<int>()((int) o2.type, (int) o2e.type);
auto o1d = o1.data;
auto o1ed = o1e.data;
auto o2d = o2.data;
auto o2ed = o2e.data;
HelpfulAssert<size_t>()(o1.data.size(), o1e.data.size());
HelpfulAssert<size_t>()(o2.data.size(), o2e.data.size());
for (int i = 0; i < o1.data.size(); i++) {
HelpfulAssert<char>()(o1.data[i], o1e.data[i]);
}
for (int i = 0; i < o2.data.size(); i++) {
HelpfulAssert<char>()(o2.data[i], o2e.data[i]);
}
HelpfulAssert<Object::idType>()(repo.getObjectId(Object::ObjectType::Chunk, o1k), 1);
HelpfulAssert<Object::idType>()(repo.getObjectId(Object::ObjectType::Chunk, o2k), 2);
repo.deleteObject(o1);
}
{
Config conf;
conf.add("repo", "testrepo");
FileRepository repo(conf);
repo.open();
std::string o2k(16, '\0');
o2k[0] = 1;
HelpfulAssert<Object::idType>()(repo.getObjectId(Object::ObjectType::Chunk, o2k), 2);
auto id = repo.getId();
HelpfulAssert<int>()(id, 1);
std::vector<char>
data1{'a', 'b', 'c', 'e'};
Chunk o1(id, o2k, data1);
HelpfulAssert<int>()(repo.getId(), 3);
}
return true;
})));
return tg;
}

View File

@@ -0,0 +1,24 @@
//
// Created by Stepan Usatiuk on 14.04.2023.
//
#ifndef SEMBACKUP_FILEREPOSITORYTEST_H
#define SEMBACKUP_FILEREPOSITORYTEST_H
#include <fstream>
#include <iostream>
#include <vector>
#include "../../src/repo/FileRepository.h"
#include "../../src/repo/objects/Chunk.h"
#include "../utils/Cleaner.h"
#include "../utils/TestGroupGenerator.h"
class FileRepositoryTest : public TestGroupGenerator {
public:
std::unique_ptr<TestGroup> operator()() override;
};
#endif//SEMBACKUP_FILEREPOSITORYTEST_H

34
tests/runTests.cpp Normal file
View File

@@ -0,0 +1,34 @@
//
// Created by Stepan Usatiuk on 13.04.2023.
//
#include <memory>
#include <vector>
#include "BuzhashTest.h"
#include "CLITestWrapper.h"
#include "crypto/AESTest.h"
#include "crypto/MD5Test.h"
#include "fulltests/FullTest.h"
#include "repo/ChunkTest.h"
#include "repo/FileRepositoryTest.h"
#include "utils/HelpfulAssertTest.h"
int main() {
std::vector<std::unique_ptr<Runnable>> tests{};
tests.emplace_back(HelpfulAssertTest()());
tests.emplace_back(MD5Test()());
tests.emplace_back(AESTest()());
tests.emplace_back(ChunkTest()());
tests.emplace_back(FileRepositoryTest()());
tests.emplace_back(BuzhashTest()());
tests.emplace_back(CLITestWrapper()());
tests.emplace_back(FullTest()());
bool ok = true;
for (const auto &t: tests) {
ok = t->run(std::cout) && ok;
}
return ok ? 0 : -1;
}

16
tests/utils/Cleaner.cpp Normal file
View File

@@ -0,0 +1,16 @@
//
// Created by Stepan Usatiuk on 14.04.2023.
//
#include "Cleaner.h"
Cleaner::Cleaner(std::vector<std::filesystem::path> toClean) : toClean(std::move(toClean)) {
for (const auto &p: this->toClean) {
std::filesystem::remove_all(p);
}
}
Cleaner::~Cleaner() {
for (const auto &p: toClean) {
std::filesystem::remove_all(p);
}
}

23
tests/utils/Cleaner.h Normal file
View File

@@ -0,0 +1,23 @@
//
// Created by Stepan Usatiuk on 14.04.2023.
//
#ifndef SEMBACKUP_CLEANER_H
#define SEMBACKUP_CLEANER_H
#include <filesystem>
#include <utility>
#include <vector>
class Cleaner {
public:
Cleaner(std::vector<std::filesystem::path> toClean);
~Cleaner();
private:
std::vector<std::filesystem::path> toClean;
};
#endif//SEMBACKUP_CLEANER_H

View File

@@ -0,0 +1,43 @@
//
// Created by Stepan Usatiuk on 13.04.2023.
//
#ifndef SEMBACKUP_HELPFULASSERT_H
#define SEMBACKUP_HELPFULASSERT_H
#include <functional>
#include <iostream>
#include <ostream>
#include <sstream>
#include <utility>
#include "../../src/Exception.h"
template<typename T, typename comp = std::equal_to<>>
class HelpfulAssert {
public:
bool operator()(const T &lhs, const T &rhs) {
if (!comp()(lhs, rhs)) {
std::stringstream out;
if constexpr (has_print_op<T>::value) {
out << "Expected lhs to compare to " << rhs << std::endl;
out << "But lhs is " << lhs << std::endl;
} else {
out << "Error comparing!" << std::endl;
}
throw Exception(out.str());
}
return true;
}
private:
template<typename, typename = void>
struct has_print_op : std::false_type {};
template<typename E>
struct has_print_op<E, std::void_t<decltype(std::declval<std::ostream>() << std::declval<E>())>> : std::true_type {};
};
#endif//SEMBACKUP_HELPFULASSERT_H

View File

@@ -0,0 +1,65 @@
//
// Created by Stepan Usatiuk on 13.04.2023.
//
#include "HelpfulAssertTest.h"
std::unique_ptr<TestGroup> HelpfulAssertTest::operator()() {
auto tg = std::make_unique<TestGroup>("HelpfulAssert tests");
tg->addTest(std::make_unique<Test>("Equal test", std::function<bool()>([]() {
HelpfulAssert<int>()(1, 1);
HelpfulAssert<std::string>()("hello", "hello");
try {
HelpfulAssert<std::string>()("hello", "hello2");
} catch (const Exception &e) {
if (std::string_view(e.what()).find("Expected lhs to compare to hello2\nBut lhs is hello\n") == std::string_view::npos)
throw Exception("HelpfulAssert text is wrong");
} catch (...) {
throw Exception("HelpfulAssert throws wrong exception");
}
try {
HelpfulAssert<int>()(1, 2);
} catch (const Exception &e) {
if (std::string_view(e.what()).find("Expected lhs to compare to 2\nBut lhs is 1\n") == std::string_view::npos)
throw Exception("HelpfulAssert text is wrong");
} catch (...) {
throw Exception("HelpfulAssert throws wrong exception");
}
return true;
})));
tg->addTest(std::make_unique<Test>("Greater than test", std::function<bool()>([]() {
HelpfulAssert<int, std::greater<>>()(2, 1);
try {
HelpfulAssert<int, std::greater<>>()(1, 2);
} catch (const Exception &e) {
if (std::string_view(e.what()).find("Expected lhs to compare to 2\nBut lhs is 1\n") == std::string_view::npos)
throw Exception("HelpfulAssert text is wrong");
} catch (...) {
throw Exception("HelpfulAssert throws wrong exception");
}
return true;
})));
tg->addTest(std::make_unique<Test>("Less than test", std::function<bool()>([]() {
HelpfulAssert<int, std::less<>>()(1, 2);
try {
HelpfulAssert<int, std::less<>>()(2, 1);
} catch (const Exception &e) {
if (std::string_view(e.what()).find("Expected lhs to compare to 1\nBut lhs is 2\n") == std::string_view::npos)
throw Exception("HelpfulAssert text is wrong");
} catch (...) {
throw Exception("HelpfulAssert throws wrong exception");
}
return true;
})));
return tg;
}

View File

@@ -0,0 +1,16 @@
//
// Created by Stepan Usatiuk on 13.04.2023.
//
#ifndef SEMBACKUP_HELPFULASSERTTEST_H
#define SEMBACKUP_HELPFULASSERTTEST_H
#include "TestGroupGenerator.h"
class HelpfulAssertTest : public TestGroupGenerator {
public:
std::unique_ptr<TestGroup> operator()() override;
};
#endif//SEMBACKUP_HELPFULASSERTTEST_H

13
tests/utils/Runnable.cpp Normal file
View File

@@ -0,0 +1,13 @@
//
// Created by Stepan Usatiuk on 13.04.2023.
//
#include "Runnable.h"
Runnable::Runnable(std::string name) : name(std::move(name)) {}
std::string Runnable::getName() {
return name;
}
Runnable::~Runnable() = default;

26
tests/utils/Runnable.h Normal file
View File

@@ -0,0 +1,26 @@
//
// Created by Stepan Usatiuk on 13.04.2023.
//
#ifndef SEMBACKUP_RUNNABLE_H
#define SEMBACKUP_RUNNABLE_H
#include <iostream>
#include <string>
class Runnable {
public:
Runnable(std::string name);
virtual bool run(std::ostream &out) = 0;
virtual ~Runnable();
std::string getName();
protected:
std::string name;
};
#endif//SEMBACKUP_RUNNABLE_H

16
tests/utils/Test.cpp Normal file
View File

@@ -0,0 +1,16 @@
//
// Created by Stepan Usatiuk on 13.04.2023.
//
#include "Test.h"
#include <utility>
Test::Test(std::string name, std::function<bool()> test)
: Runnable(std::move(name)), test(std::move(test)) {}
bool Test::run(std::ostream &out) {
return test();
}
Test::~Test() = default;

25
tests/utils/Test.h Normal file
View File

@@ -0,0 +1,25 @@
//
// Created by Stepan Usatiuk on 13.04.2023.
//
#ifndef SEMBACKUP_TEST_H
#define SEMBACKUP_TEST_H
#include <functional>
#include "Runnable.h"
class Test : public Runnable {
public:
Test(std::string name, std::function<bool()> test);
bool run(std::ostream &out) override;
~Test() override;
private:
std::function<bool()> test;
};
#endif//SEMBACKUP_TEST_H

31
tests/utils/TestGroup.cpp Normal file
View File

@@ -0,0 +1,31 @@
//
// Created by Stepan Usatiuk on 13.04.2023.
//
#include "TestGroup.h"
TestGroup::TestGroup(std::string name) : Runnable(std::move(name)) {}
bool TestGroup::run(std::ostream &out) {
bool ok = true;
out << "Running test group " << getName() << std::endl;
for (auto const &p: tests) {
out << " Running " << p->getName() << " ";
try {
p->run(out);
out << "OK";
} catch (const std::exception &e) {
ok = false;
out << "ERROR" << std::endl;
out << e.what();
}
out << std::endl;
}
return ok;
}
void TestGroup::addTest(std::unique_ptr<Runnable> &&test) {
tests.emplace_back(std::move(test));
}
TestGroup::~TestGroup() = default;

28
tests/utils/TestGroup.h Normal file
View File

@@ -0,0 +1,28 @@
//
// Created by Stepan Usatiuk on 13.04.2023.
//
#ifndef SEMBACKUP_TESTGROUP_H
#define SEMBACKUP_TESTGROUP_H
#include <memory>
#include <vector>
#include "Runnable.h"
class TestGroup : public Runnable {
public:
TestGroup(std::string name);
bool run(std::ostream &out) override;
void addTest(std::unique_ptr<Runnable> &&test);
~TestGroup() override;
private:
std::vector<std::unique_ptr<Runnable>> tests;
};
#endif//SEMBACKUP_TESTGROUP_H

View File

@@ -0,0 +1,23 @@
//
// Created by Stepan Usatiuk on 13.04.2023.
//
#ifndef SEMBACKUP_TESTGROUPGENERATOR_H
#define SEMBACKUP_TESTGROUPGENERATOR_H
#include <cassert>
#include <functional>
#include <memory>
#include <sstream>
#include "HelpfulAssert.h"
#include "Runnable.h"
#include "Test.h"
#include "TestGroup.h"
class TestGroupGenerator {
public:
virtual std::unique_ptr<TestGroup> operator()() = 0;
};
#endif//SEMBACKUP_TESTGROUPGENERATOR_H