Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
sears-s committed Jul 4, 2022
1 parent f310aa7 commit 70bb602
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 18 deletions.
37 changes: 34 additions & 3 deletions core/LocalManager/LMDatabaseManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,7 @@ GetTestcaseToMutateResponse* LMDatabaseManager::generateGetTestcaseToMutateRespo

//#################### First part: get testcase ####################
{
if (mysql_query(getDBConnection(), "SELECT ID, CreatorServiceDescriptorGUID, CreatorLocalID, RawBytes FROM interesting_testcases WHERE TestCaseType = 0 ORDER BY Rating DESC LIMIT 1") != 0) {
if (mysql_query(getDBConnection(), "SELECT ID, CreatorServiceDescriptorGUID, CreatorLocalID, RawBytes, Rating, ChosenCounter, IFNULL(Counter, 1) FROM interesting_testcases LEFT JOIN edge_coverage ON EdgeCoverageHash = Hash WHERE TestCaseType = 0 ORDER BY Rating DESC LIMIT 1") != 0) {
LOG(ERROR) << "LMDatabaseManager::generateGetTestcaseToMutateResponse could not get a testcase from the database";
return response;
}
Expand All @@ -746,6 +746,9 @@ GetTestcaseToMutateResponse* LMDatabaseManager::generateGetTestcaseToMutateRespo
long long int creatorLocalID = _strtoui64(row[2], NULL, 10);
std::string* rawBytesFirstChunk = new std::string(row[3], min(lengths[3], static_cast<unsigned int>(CommInt::chunkSizeInBytes)));
bool isOnlyOneChunk = lengths[3] <= static_cast<unsigned long>(CommInt::chunkSizeInBytes);
long long int rating = _strtoui64(row[4], NULL, 10);
long long int chosenCounter = _strtoui64(row[5], NULL, 10);
long long int pathCounter = _strtoui64(row[6], NULL, 10);

if (!isOnlyOneChunk) {
std::string* rawBytes = new std::string(row[3], lengths[3]);
Expand Down Expand Up @@ -777,6 +780,9 @@ GetTestcaseToMutateResponse* LMDatabaseManager::generateGetTestcaseToMutateRespo
response->set_allocated_id(tcID);
response->set_allocated_testcasefirstchunk(rawBytesFirstChunk);
response->set_islastchunk(isOnlyOneChunk);
response->set_rating(rating);
response->set_chosencounter(chosenCounter);
response->set_pathcounter(pathCounter);

mysql_free_result(result);
}
Expand Down Expand Up @@ -831,6 +837,31 @@ GetTestcaseToMutateResponse* LMDatabaseManager::generateGetTestcaseToMutateRespo
mysql_stmt_close(sql_stmt);
}

// Increment ChosenCounter for chosen testcase
{
// Prepared statement
MYSQL_STMT* sql_stmt = mysql_stmt_init(getDBConnection());
const char* stmt = "UPDATE interesting_testcases SET ChosenCounter = ChosenCounter + 1 WHERE ID = ?";
mysql_stmt_prepare(sql_stmt, stmt, static_cast<unsigned long>(strlen(stmt)));

// Param
MYSQL_BIND bind[1];
memset(bind, 0, sizeof(bind));
bind[0].buffer_type = MYSQL_TYPE_LONGLONG;
bind[0].buffer = &testcaseID;
bind[0].is_null = 0;
bind[0].is_unsigned = true;
bind[0].length = NULL;

// Run query
mysql_stmt_bind_param(sql_stmt, bind);
bool re = mysql_stmt_execute(sql_stmt) == 0;
if (!re) {
LOG(ERROR) << "generateGetTestcaseToMutateResponse encountered the following error (2): " << mysql_stmt_error(sql_stmt);
}
mysql_stmt_close(sql_stmt);
}

PERFORMANCE_WATCH_FUNCTION_EXIT("generateGetTestcaseToMutateResponse")
return response;
}
Expand Down Expand Up @@ -1039,12 +1070,12 @@ bool LMDatabaseManager::addEntryToInterestingTestcasesTable(const FluffiTestcase
if (edgeCoverageHash.empty())
{
bind_len = 7;
stmt = "INSERT INTO interesting_testcases (CreatorServiceDescriptorGUID, CreatorLocalID, ParentServiceDescriptorGUID, ParentLocalID, Rating, RawBytes, TestCaseType, TimeOfInsertion) values (?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP())";
stmt = "INSERT INTO interesting_testcases (CreatorServiceDescriptorGUID, CreatorLocalID, ParentServiceDescriptorGUID, ParentLocalID, Rating, RawBytes, TestCaseType, TimeOfInsertion, ChosenCounter) values (?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP(), 0)";
}
else
{
bind_len = 8;
stmt = "INSERT INTO interesting_testcases (CreatorServiceDescriptorGUID, CreatorLocalID, ParentServiceDescriptorGUID, ParentLocalID, Rating, RawBytes, TestCaseType, TimeOfInsertion, EdgeCoverageHash) values (?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP(), ?)";
stmt = "INSERT INTO interesting_testcases (CreatorServiceDescriptorGUID, CreatorLocalID, ParentServiceDescriptorGUID, ParentLocalID, Rating, RawBytes, TestCaseType, TimeOfInsertion, EdgeCoverageHash, ChosenCounter) values (?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP(), ?, 0)";
}
mysql_stmt_prepare(sql_stmt, stmt, static_cast<unsigned long>(strlen(stmt)));

Expand Down
110 changes: 99 additions & 11 deletions core/TestcaseGenerator/QueueFillerWorker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,13 @@ Author(s): Thomas Riedmaier, Abian Blome, Roman Bendt
#include "FluffiMutator.h"
#include "AFLMutator.h"

QueueFillerWorker::QueueFillerWorker(CommInt* commInt, TGWorkerThreadStateBuilder* workerThreadStateBuilder, int delayToWaitUntilConfigIsCompleteInMS, size_t desiredQueueFillLevel, std::string testcaseDirectory, std::string queueFillerTempDir, TGTestcaseManager* testcaseManager, std::set<std::string> myAgentSubTypes, GarbageCollectorWorker* garbageCollectorWorker, int maxBulkGenerationSize) :
QueueFillerWorker::QueueFillerWorker(CommInt* commInt, TGWorkerThreadStateBuilder* workerThreadStateBuilder, int delayToWaitUntilConfigIsCompleteInMS, size_t desiredQueueFillLevel, std::string testcaseDirectory, std::string queueFillerTempDir, TGTestcaseManager* testcaseManager, std::set<std::string> myAgentSubTypes, GarbageCollectorWorker* garbageCollectorWorker) :
m_gotConfigFromLM(false),
m_commInt(commInt),
m_workerThreadStateBuilder(workerThreadStateBuilder),
m_desiredQueueFillLevel(desiredQueueFillLevel),
m_queueFillerTempDir(queueFillerTempDir),
m_testcaseManager(testcaseManager),
m_bulkGenerationSize(maxBulkGenerationSize),
m_maxBulkGenerationSize(maxBulkGenerationSize),
m_mySelfServiceDescriptor(commInt->getOwnServiceDescriptor()),
m_workerThreadState(nullptr),
m_garbageCollectorWorker(garbageCollectorWorker),
Expand Down Expand Up @@ -102,31 +100,63 @@ void QueueFillerWorker::workerMain() {
}

FluffiTestcaseID parentID{ FluffiServiceDescriptor{"",""},0 };
long long int rating = 0;
long long int chosenCounter = 0;
long long int pathCounter = 0;
try
{
if (m_mutatorNeedsParents) {
parentID = getNewParent();
std::tie(parentID, rating, chosenCounter, pathCounter) = getNewParent();
}
}
catch (const std::runtime_error& e) {
LOG(ERROR) << "Failed to get a new parent (" << e.what() << ") we'll try again!";
continue;
}

// Default energy for constant power schedule
unsigned long long int energy = m_bulkGenerationSize;

// FAST power schedule
if (m_powerSchedule == "FAST")
{
if (chosenCounter > 62) // prevent overflow
{
energy = m_maxBulkGenerationSize;
}
else
{
energy = rating * (static_cast<unsigned long long int>(1) << chosenCounter) / (m_powerScheduleConstant * (pathCounter == 0 ? 1 : pathCounter));
if (energy > m_maxBulkGenerationSize)
{
energy = m_maxBulkGenerationSize;
}
else if (energy < m_minBulkGenerationSize)
{
energy = m_minBulkGenerationSize;
}
}
LOG(INFO) << "FAST Power Schedule - chosen: " << std::to_string(chosenCounter) << " paths: " << std::to_string(pathCounter) << " rating: " << std::to_string(rating) << " energy: " << std::to_string(energy);
}
else if (m_powerSchedule == "constant")
{
LOG(INFO) << "Constant Power Schedule - energy: " << std::to_string(energy);
}

//from this point on there is a parent testcase file that we have to take care of!
std::string parentPathAndFileName = Util::generateTestcasePathAndFilename(parentID, m_queueFillerTempDir);

try
{
std::deque<TestcaseDescriptor> children = m_mutator->batchMutate(m_bulkGenerationSize, parentID, parentPathAndFileName);
std::deque<TestcaseDescriptor> children = m_mutator->batchMutate(static_cast<unsigned int>(energy), parentID, parentPathAndFileName);

if (children.size() > 0)
{
m_testcaseManager->pushNewGeneratedTestcases(children);
reportNewMutations(parentID, static_cast<int>(children.size()));

//adapt bulk generation size
if (m_bulkGenerationSize < m_maxBulkGenerationSize) {
// Constant power schedule - adapt bulk generation size
if (m_powerSchedule == "constant" && m_bulkGenerationSize < m_maxBulkGenerationSize) {
m_bulkGenerationSize++;
}
}
Expand All @@ -138,8 +168,8 @@ void QueueFillerWorker::workerMain() {
catch (const std::runtime_error& e) {
LOG(ERROR) << "batchMutate failed (" << e.what() << ")!";

//adapt bulk generation size
if (m_bulkGenerationSize > 1) {
// Constant power schedule - adapt bulk generation size
if (m_powerSchedule == "constant" && m_bulkGenerationSize > 1) {
m_bulkGenerationSize--;
}
}
Expand All @@ -157,7 +187,7 @@ void QueueFillerWorker::workerMain() {
m_workerThreadStateBuilder->destructState(m_workerThreadState);
}

FluffiTestcaseID QueueFillerWorker::getNewParent()
std::tuple<FluffiTestcaseID, long long int, long long int, long long int> QueueFillerWorker::getNewParent()
{
FLUFFIMessage req;
GetTestcaseToMutateRequest* getTestcaseToMutateRequest = new GetTestcaseToMutateRequest();
Expand Down Expand Up @@ -195,7 +225,7 @@ FluffiTestcaseID QueueFillerWorker::getNewParent()
}
}

return parentID;
return std::make_tuple(parentID, receivedTestcase->rating(), receivedTestcase->chosencounter(), receivedTestcase->pathcounter());
}
else
{
Expand Down Expand Up @@ -276,6 +306,64 @@ bool QueueFillerWorker::tryGetConfigFromLM() {
_exit(EXIT_FAILURE); //make compiler happy;
}

// Set power schedule constants
if (settings.count("constantFuzz") != 0)
{
try
{
m_bulkGenerationSize = std::stoi(settings["constantFuzz"]);
}
catch (...)
{
}
}
if (settings.count("minFuzz") != 0)
{
try
{
m_minBulkGenerationSize = std::stoi(settings["minFuzz"]);
}
catch (...)
{
}
}
if (settings.count("maxFuzz") != 0)
{
try
{
m_maxBulkGenerationSize = std::stoi(settings["maxFuzz"]);
}
catch (...)
{
}
}
if (settings.count("fastConstant") != 0)
{
try
{
m_powerScheduleConstant = std::stoi(settings["fastConstant"]);
}
catch (...)
{
}
}

// Set power schedule
if (settings.count("powerSchedule") == 0 || settings["powerSchedule"] != "FAST")
{
m_powerSchedule = "constant";
}
else
{
m_powerSchedule = "FAST";
}

// Constant power schedule by default starts at maximum
if (m_powerSchedule == "constant" && settings.count("maxFuzz") == 0)
{
m_maxBulkGenerationSize = m_bulkGenerationSize;
}

//check if the setup is actually working
bool isSetupFunctionable = m_mutator->isSetupFunctionable();
if (!isSetupFunctionable) {
Expand Down
11 changes: 7 additions & 4 deletions core/TestcaseGenerator/QueueFillerWorker.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class FluffiMutator;
class QueueFillerWorker
{
public:
QueueFillerWorker(CommInt* commInt, TGWorkerThreadStateBuilder* workerThreadStateBuilder, int delayToWaitUntilConfigIsCompleteInMS, size_t desiredQueueFillLevel, std::string testcaseDirectory, std::string queueFillerTempDir, TGTestcaseManager* testcaseManager, std::set<std::string> myAgentSubTypes, GarbageCollectorWorker* garbageCollectorWorker, int maxBulkGenerationSize = 50);
QueueFillerWorker(CommInt* commInt, TGWorkerThreadStateBuilder* workerThreadStateBuilder, int delayToWaitUntilConfigIsCompleteInMS, size_t desiredQueueFillLevel, std::string testcaseDirectory, std::string queueFillerTempDir, TGTestcaseManager* testcaseManager, std::set<std::string> myAgentSubTypes, GarbageCollectorWorker* garbageCollectorWorker);
virtual ~QueueFillerWorker();

void workerMain();
Expand All @@ -44,7 +44,7 @@ class QueueFillerWorker
std::thread* m_thread = nullptr;

private:
FluffiTestcaseID getNewParent();
std::tuple<FluffiTestcaseID, long long int, long long int, long long int> getNewParent();
void reportNewMutations(FluffiTestcaseID id, int numOfNewMutations);
bool tryGetConfigFromLM();

Expand All @@ -54,8 +54,11 @@ class QueueFillerWorker
size_t m_desiredQueueFillLevel;
std::string m_queueFillerTempDir;
TGTestcaseManager* m_testcaseManager;
int m_bulkGenerationSize;
int m_maxBulkGenerationSize;
std::string m_powerSchedule = "constant";
unsigned int m_bulkGenerationSize = 50; // only for constant PS
unsigned int m_minBulkGenerationSize = 30;
unsigned int m_maxBulkGenerationSize = 500;
unsigned int m_powerScheduleConstant = 100;
FluffiServiceDescriptor m_mySelfServiceDescriptor;
TGWorkerThreadState* m_workerThreadState;
GarbageCollectorWorker* m_garbageCollectorWorker;
Expand Down
3 changes: 3 additions & 0 deletions core/dependencies/libprotoc/FLUFFI.proto
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,9 @@ message GetTestcaseToMutateResponse{
bytes testCaseFirstChunk = 2; //up to CommInt::chunkSizeInBytes bytes
bool isLastChunk = 3;
bool alsoRunWithoutMutation = 4;
int64 rating = 5;
int64 chosenCounter = 6;
int64 pathCounter = 7;
}

message ReportTestcaseWithNoResultRequest{
Expand Down
1 change: 1 addition & 0 deletions srv/fluffi/data/fluffiweb/app/sql_files/createLMDB.sql
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ CREATE TABLE IF NOT EXISTS fluffi.interesting_testcases (
`TestCaseType` INT(1) NOT NULL,
`TimeOfInsertion` TIMESTAMP NULL DEFAULT NULL,
`EdgeCoverageHash` CHAR(16) NULL DEFAULT NULL,
`ChosenCounter` BIGINT NOT NULL DEFAULT 0,
UNIQUE (`CreatorServiceDescriptorGUID`, `CreatorLocalID`),
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Expand Down

0 comments on commit 70bb602

Please sign in to comment.