Skip to content

Commit

Permalink
Add tests for SpaceScanner
Browse files Browse the repository at this point in the history
Fix bug when scanner could hang if it was destroyed immediately
after construction.
Fix possible CPU consume in paused state.
Fix incorrect counting of inotify watches.
  • Loading branch information
funbiscuit committed May 5, 2020
1 parent be5ea1c commit 4e28440
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 5 deletions.
5 changes: 2 additions & 3 deletions lib/src/spacescanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include <chrono>

SpaceScanner::SpaceScanner() :
scannerStatus(ScannerStatus::IDLE), runWorker(false), isMountScanned(false),
scannerStatus(ScannerStatus::IDLE), runWorker(true), isMountScanned(false),
watcherLimitExceeded(false)
{
db = std::make_shared<FileDB>();
Expand Down Expand Up @@ -59,7 +59,6 @@ void SpaceScanner::checkForEvents()
void SpaceScanner::worker_run()
{
std::cout << "Start worker thread\n";
runWorker = true;
while(runWorker)
{
std::unique_lock<std::mutex> scanLock(scanMtx, std::defer_lock);
Expand All @@ -82,7 +81,7 @@ void SpaceScanner::worker_run()
std::vector<std::unique_ptr<FilePath>> newPaths;

update_disk_space();
while(!scanQueue.empty() && scannerStatus==ScannerStatus::SCANNING)
while(!scanQueue.empty() && scannerStatus!=ScannerStatus::IDLE)
{
auto scanRequest = std::move(scanQueue.front());
scanQueue.pop_front();
Expand Down
11 changes: 9 additions & 2 deletions lib/src/spacewatcher-linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,14 @@ SpaceWatcher::AddDirStatus SpaceWatcherLinux::addDir(const std::string &path)
return AddDirStatus::ACCESS_DENIED; //this is a default, although not very accurate
}
std::lock_guard<std::mutex> lock(inotifyWdsMtx);
inotifyWds[wd]=path;
SpaceWatcher::addDir(path);
auto it = inotifyWds.find(wd);
if(it!=inotifyWds.end())
it->second = path;
else
{
inotifyWds[wd]=path;
SpaceWatcher::addDir(path);
}
return AddDirStatus::ADDED;
}

Expand All @@ -105,6 +111,7 @@ void SpaceWatcherLinux::_addEvent(struct inotify_event *inotifyEvent)
auto it = inotifyWds.find(inotifyEvent->wd);
if(it != inotifyWds.end())
{
SpaceWatcher::rmDir(it->second);
inotifyWds.erase(it);
}
return;
Expand Down
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ target_sources(spacedisplay_test PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/FileEntryTest.cpp
${CMAKE_CURRENT_SOURCE_DIR}/FileDBTest.cpp
${CMAKE_CURRENT_SOURCE_DIR}/FilePathTest.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ScannerTest.cpp
${CMAKE_CURRENT_SOURCE_DIR}/SpaceWatcherTest.cpp
${CMAKE_CURRENT_SOURCE_DIR}/UtilsTest.cpp
${CMAKE_CURRENT_SOURCE_DIR}/DirHelper.cpp
Expand Down
178 changes: 178 additions & 0 deletions tests/ScannerTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@

#include <catch.hpp>

#include "spacescanner.h"
#include "filepath.h"
#include "filedb.h"
#include "utils.h"
#include "DirHelper.h"


TEST_CASE( "Scanner tests", "[scanner]" )
{
auto scanner = Utils::make_unique<SpaceScanner>();

REQUIRE_FALSE( scanner->is_loaded() );

std::unique_ptr<FilePath> curScanPath;

scanner->getCurrentScanPath(curScanPath);

REQUIRE( curScanPath == nullptr );

SECTION( "Scan custom path" )
{
DirHelper dh("TestDir");
dh.createDir("test");
dh.createFile("test/test.txt");
dh.createFile("test/test2.txt");
dh.createDir("test3");
dh.createFile("test3/test.txt");
dh.createFile("test3/test2.txt");
dh.createFile("test3/test3.txt");
dh.createFile("test3/test4.txt");
dh.createDir("test3/test5");
dh.createFile("test3/test5/test1.txt");
dh.createFile("test3/test5/test2.txt");
dh.createFile("test3/test5/test3.txt");

REQUIRE( scanner->scan_dir("TestDir2") == ScannerError::CANT_OPEN_DIR );
REQUIRE( scanner->scan_dir("TestDir") == ScannerError::NONE );
REQUIRE( scanner->scan_dir("TestDir") == ScannerError::SCAN_RUNNING );

REQUIRE( scanner->is_loaded() );
REQUIRE( scanner->getRootPath() != nullptr );
REQUIRE( scanner->canPause() );
REQUIRE_FALSE( scanner->canResume() );
REQUIRE_FALSE( scanner->isProgressKnown() );
REQUIRE( scanner->has_changes() );
REQUIRE( scanner->can_refresh() );

//wait for scanner to complete
while ( scanner->get_scan_progress()<100 )
std::this_thread::sleep_for(std::chrono::milliseconds(1));

REQUIRE_FALSE( scanner->canPause() );
REQUIRE_FALSE( scanner->canResume() );
REQUIRE( scanner->has_changes() );
REQUIRE( scanner->can_refresh() );

REQUIRE( scanner->getDirCount() == 4 );
REQUIRE( scanner->getFileCount() == 9 );
scanner->rescan_dir(FilePath("TestDir"));
REQUIRE( scanner->canPause() );
REQUIRE_FALSE( scanner->canResume() );


//wait for scanner to complete
while ( scanner->get_scan_progress()<100 )
std::this_thread::sleep_for(std::chrono::milliseconds(1));

REQUIRE( scanner->getDirCount() == 4 );
REQUIRE( scanner->getFileCount() == 9 );

dh.createDir("test3/test2");
dh.createFile("test3/test2/test1.txt");
dh.createFile("test3/test2/test2.txt");
dh.createFile("test3/test2/test3.txt");
dh.createDir("test3/test1");
dh.createFile("test3/test1/test2.txt");
dh.createFile("test3/test1/test3.txt");
//wait for scanner to detect changes
std::this_thread::sleep_for(std::chrono::milliseconds(50));

REQUIRE( scanner->getDirCount() == 6 );
REQUIRE( scanner->getFileCount() == 14 );

dh.createDir("test3/test10");
dh.createFile("test3/test10/test2.txt");
dh.createFile("test3/test10/test3.txt");
dh.createDir("test3/test10/test2");
dh.createFile("test3/test10/test2/test1.txt");
dh.createFile("test3/test10/test2/test2.txt");
FilePath path("TestDir");
path.addDir("test3");

//wait for scanner to finish
std::this_thread::sleep_for(std::chrono::milliseconds(60));
REQUIRE_FALSE( scanner->canPause() );
REQUIRE_FALSE( scanner->canResume() );
REQUIRE( scanner->get_scan_progress() == 100 );

REQUIRE( scanner->getDirCount() == 8 );
REQUIRE( scanner->getFileCount() == 18 );

int64_t watchedNow, limit;
bool exceeded = scanner->getWatcherLimits(watchedNow, limit);
REQUIRE_FALSE( exceeded );
REQUIRE( watchedNow == scanner->getDirCount() );

dh.deleteDir("test3/test10");
std::this_thread::sleep_for(std::chrono::milliseconds(60));
scanner->getWatcherLimits(watchedNow, limit);
REQUIRE( watchedNow == scanner->getDirCount() );
}
SECTION( "Scan root" )
{
auto roots = scanner->get_available_roots();
REQUIRE_FALSE( roots.empty() );
REQUIRE( scanner->scan_dir(roots.front()) == ScannerError::NONE );
REQUIRE( scanner->is_loaded() );
REQUIRE( scanner->getRootPath() != nullptr );
REQUIRE( scanner->canPause() );
REQUIRE_FALSE( scanner->canResume() );
REQUIRE( scanner->isProgressKnown() );
REQUIRE( scanner->has_changes() );
REQUIRE( scanner->can_refresh() );

//wait for scanner to start scanning
std::this_thread::sleep_for(std::chrono::milliseconds(50));

SECTION("Pause and stop running scan")
{
REQUIRE( scanner->canPause() );
REQUIRE_FALSE( scanner->canResume() );
REQUIRE( scanner->pauseScan() );
REQUIRE_FALSE( scanner->canPause() );
REQUIRE( scanner->canResume() );

//wait for scanner to actually pause
std::this_thread::sleep_for(std::chrono::milliseconds(100));
REQUIRE_FALSE( scanner->canPause() );
REQUIRE( scanner->canResume() );
scanner->getCurrentScanPath(curScanPath);
REQUIRE( curScanPath != nullptr );
scanner->getCurrentScanPath(curScanPath);
REQUIRE( curScanPath != nullptr );

REQUIRE( scanner->has_changes() );
auto db = scanner->getFileDB();
REQUIRE( db != nullptr );
auto root = scanner->getRootPath();
REQUIRE( root != nullptr );
auto processed = db->processEntry(*root,[](const FileEntry& entry){});
REQUIRE( processed );
REQUIRE_FALSE( scanner->has_changes() );

REQUIRE( scanner->getDirCount() > 0 );
REQUIRE( scanner->getFileCount() > 0 );

REQUIRE( scanner->resumeScan() );
std::this_thread::sleep_for(std::chrono::milliseconds(100));

REQUIRE( scanner->canPause() );
REQUIRE_FALSE( scanner->canResume() );
scanner->stop_scan();
REQUIRE_FALSE( scanner->canPause() );
REQUIRE_FALSE( scanner->canResume() );
REQUIRE( scanner->get_scan_progress() == 100 );

uint64_t used, available, total;
scanner->getSpace(used, available, total);
REQUIRE( used > 0 );
REQUIRE( available > 0 );
REQUIRE( total > 0 );
REQUIRE( (total-available) >= used );
}
}
}

0 comments on commit 4e28440

Please sign in to comment.