diff options
| author | 2024-12-28 15:00:29 +0100 | |
|---|---|---|
| committer | 2024-12-29 14:46:30 +0100 | |
| commit | 5c508b351a95f416e4a599f76902b888369de1b4 (patch) | |
| tree | e3f6363fd7458fb0a46eabde6bd3a65b4746d798 /src | |
| parent | 5515cd5a22ab97843f6ca1c234333ec110a9bab1 (diff) | |
| download | OneRoll-5c508b351a95f416e4a599f76902b888369de1b4.tar.gz OneRoll-5c508b351a95f416e4a599f76902b888369de1b4.zip | |
Several fix from fuzzer test.
Diffstat (limited to 'src')
| -rw-r--r-- | src/bin/cli/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/libparser/booleancondition.cpp | 4 | ||||
| -rw-r--r-- | src/libparser/diceparser.cpp | 4 | ||||
| -rw-r--r-- | src/libparser/die.cpp | 12 | ||||
| -rw-r--r-- | src/libparser/die.h | 1 | ||||
| -rw-r--r-- | src/libparser/node/bind.cpp | 37 | ||||
| -rw-r--r-- | src/libparser/node/executionnode.cpp | 19 | ||||
| -rw-r--r-- | src/libparser/node/executionnode.h | 5 | ||||
| -rw-r--r-- | src/libparser/node/jumpbackwardnode.cpp | 9 | ||||
| -rw-r--r-- | src/libparser/node/jumpbackwardnode.h | 1 | ||||
| -rw-r--r-- | src/libparser/node/mergenode.cpp | 98 | ||||
| -rw-r--r-- | src/libparser/node/mergenode.h | 6 | ||||
| -rw-r--r-- | src/libparser/node/rerolldicenode.cpp | 61 | ||||
| -rw-r--r-- | src/libparser/parsingtoolbox.cpp | 35 | ||||
| -rw-r--r-- | src/libparser/result/diceresult.cpp | 2 | ||||
| -rw-r--r-- | src/tests/dice/tst_dice.cpp | 57 |
16 files changed, 225 insertions, 128 deletions
diff --git a/src/bin/cli/CMakeLists.txt b/src/bin/cli/CMakeLists.txt index 6e17c1e..606bb90 100644 --- a/src/bin/cli/CMakeLists.txt +++ b/src/bin/cli/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.16) -#project(dice) +project(dice) option(UPDATE_TRANSLATIONS "update Translation" OFF) option(NO_PAINTER_OPERATOR "No PAINTING" OFF) diff --git a/src/libparser/booleancondition.cpp b/src/libparser/booleancondition.cpp index ab5b15d..12fb54b 100644 --- a/src/libparser/booleancondition.cpp +++ b/src/libparser/booleancondition.cpp @@ -93,6 +93,8 @@ BooleanCondition::~BooleanCondition() } qint64 BooleanCondition::hasValid(Die* b, bool recursive, bool unhighlight) const { + if(!b) + return 0; QList<qint64> listValues; if(m_conditionType == Dice::OnEachValue) { @@ -185,7 +187,7 @@ Dice::CONDITION_STATE BooleanCondition::isValidRangeSize(const std::pair<qint64, { Dice::CONDITION_STATE state; auto valueScalar= valueToScalar(); - qint64 boundValue= qBound(range.first, valueScalar, range.second); + qint64 boundValue= qBound(std::min(range.first, range.second), valueScalar, std::max(range.first, range.second)); bool isInsideRange= (boundValue == valueScalar); switch(m_operator) { diff --git a/src/libparser/diceparser.cpp b/src/libparser/diceparser.cpp index 43ee9ff..9f6a3dc 100644 --- a/src/libparser/diceparser.cpp +++ b/src/libparser/diceparser.cpp @@ -175,7 +175,7 @@ QMap<Dice::ERROR_CODE, QString> DiceParser::errorMap() const } QString DiceParser::humanReadableError() const { - auto parsingError= m_parsingToolbox->getErrorList(); + auto const& parsingError= m_parsingToolbox->getErrorList(); QString str; std::for_each(parsingError.begin(), parsingError.end(), [&str](const QString& text) @@ -185,7 +185,7 @@ QString DiceParser::humanReadableError() const }); /// list - auto errMap= errorMap(); + auto const& errMap= errorMap(); std::for_each(errMap.begin(), errMap.end(), [&str](const QString& text) { diff --git a/src/libparser/die.cpp b/src/libparser/die.cpp index f752bbc..021ba5e 100644 --- a/src/libparser/die.cpp +++ b/src/libparser/die.cpp @@ -58,6 +58,7 @@ Die::Die() Die::Die(const Die& die) { + // qDebug() << "dice copy" << m_rollResult.size() << die.m_rollResult.size(); m_value= die.m_value; m_rollResult= die.m_rollResult; m_selected= die.m_selected; @@ -69,8 +70,11 @@ Die::Die(const Die& die) m_base= die.m_base; m_color= die.getColor(); m_op= die.getOp(); - // auto seed= std::chrono::high_resolution_clock::now().time_since_epoch().count(); - // m_rng= std::mt19937(quintptr(this) + static_cast<unsigned long long>(seed)); +} + +Die::~Die() +{ + // qDebug() << "die destruction" << m_uuid << this; } void Die::setValue(qint64 r) @@ -153,6 +157,7 @@ bool Die::hasChildrenValue() } void Die::replaceLastValue(qint64 value) { + // qDebug() << "replace value" << value; if(!m_rollResult.isEmpty()) m_rollResult.removeLast(); insertRollValue(value); @@ -160,9 +165,6 @@ void Die::replaceLastValue(qint64 value) void Die::roll(bool adding) { - if(std::abs(m_base) >= std::abs(m_maxValue)) - return; - std::uniform_int_distribution<qint64> dist(m_base, m_maxValue); qint64 value= dist(s_rng); if((adding) || (m_rollResult.isEmpty())) diff --git a/src/libparser/die.h b/src/libparser/die.h index 2da2006..48da214 100644 --- a/src/libparser/die.h +++ b/src/libparser/die.h @@ -42,6 +42,7 @@ public: * @brief Die */ Die(const Die&); + ~Die(); /** * @brief setValue * @param r diff --git a/src/libparser/node/bind.cpp b/src/libparser/node/bind.cpp index 41449d8..9c502df 100644 --- a/src/libparser/node/bind.cpp +++ b/src/libparser/node/bind.cpp @@ -38,27 +38,36 @@ void BindNode::run(ExecutionNode* previous) for(auto start : *m_startList) { ExecutionNode* last= getLatestNode(start); - if(nullptr != last) + if(!last) + continue; + + auto tmpResult= last->getResult(); + QSet<Result*> alreadyVisited; + while(nullptr != tmpResult && !alreadyVisited.contains(tmpResult)) { - auto tmpResult= last->getResult(); - while(nullptr != tmpResult) + alreadyVisited.insert(tmpResult); + DiceResult* dice= dynamic_cast<DiceResult*>(tmpResult); + + if(nullptr != dice) { - DiceResult* dice= dynamic_cast<DiceResult*>(tmpResult); - if(nullptr != dice) + m_diceResult->setHomogeneous(false); + auto list= dice->getResultList(); + for(int i= 0; i < list.size(); ++i) { - m_diceResult->setHomogeneous(false); - for(auto& die : dice->getResultList()) + auto die= list[i]; + + if(!die) + continue; + + if(!die->hasBeenDisplayed()) { - if(!die->hasBeenDisplayed()) - { - Die* tmpdie= new Die(*die); - die->displayed(); - m_diceResult->getResultList().append(tmpdie); - } + Die* tmpdie= new Die(*die); + die->displayed(); + m_diceResult->getResultList().append(tmpdie); } } - tmpResult= tmpResult->getPrevious(); } + tmpResult= tmpResult->getPrevious(); } } } diff --git a/src/libparser/node/executionnode.cpp b/src/libparser/node/executionnode.cpp index 096c8fe..b231416 100644 --- a/src/libparser/node/executionnode.cpp +++ b/src/libparser/node/executionnode.cpp @@ -2,6 +2,16 @@ #include <QUuid> +namespace +{ +#ifdef QT_DEBUG +constexpr int WaitingTime{2 * 1000 * 60}; +#else +constexpr int WaitingTime{30 * 60 * 1000}; +#endif + +} // namespace + ExecutionNode::ExecutionNode() : m_previousNode(nullptr) , m_result(nullptr) @@ -43,12 +53,19 @@ ExecutionNode* ExecutionNode::getNextNode() void ExecutionNode::execute(ExecutionNode* previous) { + QElapsedTimer timer; + timer.start(); + auto errorCount= m_errors.count(); run(previous); - if(m_nextNode && errorCount == m_errors.count()) + auto timeLimit= timer.hasExpired(WaitingTime); + + if(m_nextNode && errorCount == m_errors.count() && !timeLimit) m_nextNode->execute(this); + else if(timeLimit) + qDebug() << "Error too long" << WaitingTime << timeLimit << timer.elapsed(); } QMap<Dice::ERROR_CODE, QString> ExecutionNode::getExecutionErrorMap() diff --git a/src/libparser/node/executionnode.h b/src/libparser/node/executionnode.h index 342ae36..a2912e3 100644 --- a/src/libparser/node/executionnode.h +++ b/src/libparser/node/executionnode.h @@ -6,6 +6,7 @@ #include <diceparser/diceparserhelper.h> #include <QCoreApplication> +#include <QElapsedTimer> /** * @brief The ExecutionNode class */ @@ -87,7 +88,7 @@ public: protected: /** - * @brief m_nextNode + * @brief previous */ ExecutionNode* m_previousNode= nullptr; /** @@ -102,9 +103,7 @@ protected: * @brief m_errors */ QMap<Dice::ERROR_CODE, QString> m_errors; - QMap<Dice::ERROR_CODE, QString> m_warnings; - QString m_id; }; diff --git a/src/libparser/node/jumpbackwardnode.cpp b/src/libparser/node/jumpbackwardnode.cpp index e4ae59a..3e2f4c1 100644 --- a/src/libparser/node/jumpbackwardnode.cpp +++ b/src/libparser/node/jumpbackwardnode.cpp @@ -29,6 +29,11 @@ JumpBackwardNode::JumpBackwardNode() m_result= m_diceResult; } +JumpBackwardNode::~JumpBackwardNode() +{ + delete m_diceResult; +} + qint64 JumpBackwardNode::getPriority() const { return 4; @@ -126,13 +131,13 @@ void JumpBackwardNode::run(ExecutionNode* previous) for(auto& die : diceResult->getResultList()) { Die* tmpdie= new Die(*die); - //*tmpdie= *die; m_diceResult->insertResult(tmpdie); die->displayed(); } } - m_result->setPrevious(previous->getResult()); + if(m_result && previous) + m_result->setPrevious(previous->getResult()); if(m_nextNode) m_nextNode->execute(this); diff --git a/src/libparser/node/jumpbackwardnode.h b/src/libparser/node/jumpbackwardnode.h index 5f20291..2e14a00 100644 --- a/src/libparser/node/jumpbackwardnode.h +++ b/src/libparser/node/jumpbackwardnode.h @@ -33,6 +33,7 @@ public: * @brief JumpBackwardNode allows to get result from remote node in the execution tree. */ JumpBackwardNode(); + virtual ~JumpBackwardNode(); /** * @brief run - performs the actions * @param previous diff --git a/src/libparser/node/mergenode.cpp b/src/libparser/node/mergenode.cpp index 4c19bd7..8f30289 100644 --- a/src/libparser/node/mergenode.cpp +++ b/src/libparser/node/mergenode.cpp @@ -23,75 +23,82 @@ #include <diceparser/parsingtoolbox.h> -MergeNode::MergeNode() : m_diceResult(new DiceResult()) +MergeNode::MergeNode(std::vector<ExecutionNode*>& startList) : m_startList(startList), m_diceResult(new DiceResult()) { m_result= m_diceResult; } + +int findDistance(const std::vector<ExecutionNode*>& startList, MergeNode* node) +{ + int i= 0; + for(auto start : startList) + { + auto temp= start; + while(temp != nullptr) + { + if(temp == node) + return i; + temp= temp->getNextNode(); + } + ++i; + } + return i; +} void MergeNode::run(ExecutionNode* previous) { if(isValid(!previous, Dice::ERROR_CODE::NO_PREVIOUS_ERROR, tr("No previous node before Merge operator"))) return; - m_previousNode= previous; - m_result->setPrevious(previous->getResult()); - ExecutionNode* previousLast= nullptr; - std::vector<Result*> pastResult; - if(!m_startList) + // m_previousNode= previous; + // m_result->setPrevious(previous->getResult()); + // std::vector<Result*> pastResult; + if(isValid(m_startList.empty(), Dice::ERROR_CODE::NO_PREVIOUS_ERROR, tr("No several instruction"))) return; - for(auto start : *m_startList) - { - ExecutionNode* last= getLatestNode(start); - if(nullptr == last || nullptr == previousLast) - { - previousLast= last; - continue; - } - - auto startResult= start->getResult(); - if(nullptr == startResult) - continue; + auto instId= findDistance(m_startList, this); - startResult->setPrevious(previousLast->getResult()); - previousLast->setNextNode(start); + ExecutionNode* previousLast= nullptr; + std::for_each(std::begin(m_startList), std::end(m_startList), + [&previousLast, this](ExecutionNode* node) + { + ExecutionNode* last= getLatestNode(node); + if(previousLast) + { + previousLast->setNextNode(node); + auto resultNode= node->getResult(); + if(resultNode) + resultNode->setPrevious(previousLast->getResult()); + } + previousLast= last; + }); - previousLast= last; - Result* tmpResult= last->getResult(); + if(instId != 0) + { + Result* tmpResult= previous->getResult(); while(nullptr != tmpResult) { DiceResult* dice= dynamic_cast<DiceResult*>(tmpResult); - if(nullptr != dice) + if(nullptr != dice && dice != m_diceResult) { - ///@todo TODO improve here to set homogeneous while is really m_diceResult->setHomogeneous(false); + for(auto& die : dice->getResultList()) { if(!m_diceResult->getResultList().contains(die) && (!die->hasBeenDisplayed())) { Die* tmpdie= new Die(*die); die->displayed(); - m_diceResult->getResultList().append(tmpdie); + m_diceResult->insertResult(tmpdie); } } } - auto it= std::find_if(pastResult.begin(), pastResult.end(), - [tmpResult](const Result* a) { return (a == tmpResult->getPrevious()); }); - if(it == pastResult.end()) - { - pastResult.push_back(previousLast->getResult()); - tmpResult= tmpResult->getPrevious(); - } - else - { - tmpResult->setPrevious(nullptr); - tmpResult= nullptr; - } + tmpResult= tmpResult->getPrevious(); } } - auto first= m_startList->front(); - m_startList->clear(); - m_startList->push_back(first); + auto first= m_startList.front(); + m_startList.clear(); + m_startList.push_back(first); } #include <QDebug> ExecutionNode* MergeNode::getLatestNode(ExecutionNode* node) @@ -126,7 +133,7 @@ qint64 MergeNode::getPriority() const } ExecutionNode* MergeNode::getCopy() const { - MergeNode* node= new MergeNode(); + MergeNode* node= new MergeNode(m_startList); if(nullptr != m_nextNode) { node->setNextNode(m_nextNode->getCopy()); @@ -134,12 +141,7 @@ ExecutionNode* MergeNode::getCopy() const return node; } -std::vector<ExecutionNode*>* MergeNode::getStartList() const -{ - return m_startList; -} - -void MergeNode::setStartList(std::vector<ExecutionNode*>* startList) +/*void MergeNode::setStartList(const std::vector<ExecutionNode*>& startList) { m_startList= startList; -} +}*/ diff --git a/src/libparser/node/mergenode.h b/src/libparser/node/mergenode.h index 515a2e9..1b32352 100644 --- a/src/libparser/node/mergenode.h +++ b/src/libparser/node/mergenode.h @@ -31,20 +31,18 @@ class MergeNode : public ExecutionNode { public: - MergeNode(); + MergeNode(std::vector<ExecutionNode*>& startList); void run(ExecutionNode* previous); virtual QString toString(bool withLabel) const; virtual qint64 getPriority() const; virtual ExecutionNode* getCopy() const; - std::vector<ExecutionNode*>* getStartList() const; - void setStartList(std::vector<ExecutionNode*>* startList); private: ExecutionNode* getLatestNode(ExecutionNode* node); private: + std::vector<ExecutionNode*>& m_startList; DiceResult* m_diceResult= nullptr; - std::vector<ExecutionNode*>* m_startList= nullptr; }; #endif // NUMBERNODE_H diff --git a/src/libparser/node/rerolldicenode.cpp b/src/libparser/node/rerolldicenode.cpp index af075ce..25143ac 100644 --- a/src/libparser/node/rerolldicenode.cpp +++ b/src/libparser/node/rerolldicenode.cpp @@ -19,74 +19,81 @@ RerollDiceNode::~RerollDiceNode() } void RerollDiceNode::run(ExecutionNode* previous) { - if(isValid(!previous, Dice::ERROR_CODE::NO_PREVIOUS_ERROR, tr("No Previous node"))) + using DE= Dice::ERROR_CODE; + using DC= Dice::CONDITION_STATE; + if(isValid(!previous, DE::NO_PREVIOUS_ERROR, tr("No Previous node"))) return; m_previousNode= previous; auto previousDiceResult= previous->getResult(); - if(isValid(!previousDiceResult, Dice::ERROR_CODE::NO_VALID_RESULT, tr("No Valid result"))) + if(isValid(!previousDiceResult, DE::NO_VALID_RESULT, tr("No Valid result"))) return; DiceResult* previous_result= dynamic_cast<DiceResult*>(previousDiceResult); - if(isValid(!previous_result, Dice::ERROR_CODE::DIE_RESULT_EXPECTED, + if(isValid(!previous_result, DE::DIE_RESULT_EXPECTED, tr(" The a operator expects dice result. Please check the documentation and fix your command."))) return; m_result->setPrevious(previous_result); - for(auto& die : previous_result->getResultList()) + for(auto const& die : previous_result->getResultList()) { + if(!die) + return; + Die* tmpdie= new Die(*die); m_diceResult->insertResult(tmpdie); die->displayed(); } - // m_diceResult->setResultList(list); QList<Die*>& list= m_diceResult->getResultList(); QList<Die*> toRemove; - for(auto& die : list) + for(int i= 0; i < list.size(); ++i) { + auto die= list[i]; + if(!die) + continue; + bool finished= false; auto state = m_validatorList->isValidRangeSize(std::make_pair<qint64, qint64>(die->getBase(), die->getMaxValue())); - if((Dice::CONDITION_STATE::ALWAYSTRUE == state && m_adding) - || (!m_reroll && !m_adding && state == Dice::CONDITION_STATE::UNREACHABLE)) + + if(isValid((DC::ALWAYSTRUE == state && m_adding) || (!m_reroll && !m_adding && state == DC::UNREACHABLE), + DE::ENDLESS_LOOP_ERROR, + QStringLiteral("Condition cause an endless loop with this dice: %1") + .arg(QStringLiteral("d[%1,%2]") + .arg(static_cast<int>(die->getBase())) + .arg(static_cast<int>(die->getMaxValue()))))) { - m_errors.insert(Dice::ERROR_CODE::ENDLESS_LOOP_ERROR, - QObject::tr("Condition (%1) cause an endless loop with this dice: %2") - .arg(toString(true)) - .arg(QStringLiteral("d[%1,%2]") - .arg(static_cast<int>(die->getBase())) - .arg(static_cast<int>(die->getMaxValue())))); continue; } + while(m_validatorList->hasValid(die, false) && !finished) { - if(m_instruction != nullptr) + if(m_instruction) { m_instruction->execute(this); auto lastNode= ParsingToolBox::getLeafNode(m_instruction); - if(lastNode != nullptr) + if(lastNode == nullptr) + continue; + auto lastResult= dynamic_cast<DiceResult*>(lastNode->getResult()); + if(lastResult != nullptr) { - auto lastResult= dynamic_cast<DiceResult*>(lastNode->getResult()); - if(lastResult != nullptr) - { - toRemove.append(die); - list.append(lastResult->getResultList()); - lastResult->clear(); - } + toRemove.append(die); + if(list.size() < lastResult->getResultList().size()) + break; + list.append(lastResult->getResultList()); + die= list[i]; + lastResult->clear(); } } else { die->roll(m_adding); } - if(m_reroll) - { - finished= true; - } + finished= m_reroll; } } diff --git a/src/libparser/parsingtoolbox.cpp b/src/libparser/parsingtoolbox.cpp index 4d75ede..a7b089d 100644 --- a/src/libparser/parsingtoolbox.cpp +++ b/src/libparser/parsingtoolbox.cpp @@ -306,6 +306,8 @@ Validator* ParsingToolBox::readValidator(QString& str, bool hasSquare) qint64 start= operandNode->getScalarResult(); Range* range= new Range(); range->setConditionType(opCompare); + if(start > end) + qDebug() << "ERRORRR"; range->setValue(start, end); returnVal= range; isRange= true; @@ -361,12 +363,13 @@ ValidatorList* ParsingToolBox::readValidatorList(QString& str) str= str.remove(0, 1); expectSquareBrasket= true; } + ValidatorList* result{nullptr}; Validator* tmp= readValidator(str, expectSquareBrasket); Dice::LogicOperation opLogic; QVector<Dice::LogicOperation> operators; QList<Validator*> validatorList; - + bool isOK{true}; while(nullptr != tmp) { bool hasOperator= readLogicOperation(str, opLogic); @@ -381,23 +384,26 @@ ValidatorList* ParsingToolBox::readValidatorList(QString& str) if((expectSquareBrasket) && (str.startsWith("]"))) { str= str.remove(0, 1); - // isOk=true; + isOK= true; + } + else + { + // addError(Dice::ERROR_CODE::BAD_SYNTAXE, + // QStringLiteral("Syntax Error: no closing square bracket: %1").arg(str)); } validatorList.append(tmp); tmp= nullptr; } } - if(!validatorList.isEmpty()) - { - ValidatorList* validator= new ValidatorList(); - validator->setOperationList(operators); - validator->setValidators(validatorList); - return validator; - } - else + + if(!validatorList.isEmpty() && isOK) { - return nullptr; + result= new ValidatorList(); + result->setOperationList(operators); + result->setValidators(validatorList); } + + return result; } bool ParsingToolBox::readLogicOperation(QString& str, Dice::LogicOperation& op) { @@ -1820,8 +1826,8 @@ bool ParsingToolBox::readOption(QString& str, ExecutionNode* previous) //, break; case Merge: { - MergeNode* mergeNode= new MergeNode(); - mergeNode->setStartList(&m_startNodes); + MergeNode* mergeNode= new MergeNode(m_startNodes); + // mergeNode->setStartList(m_startNodes); previous->setNextNode(mergeNode); found= true; } @@ -1844,7 +1850,8 @@ bool ParsingToolBox::readOption(QString& str, ExecutionNode* previous) //, { auto scNode= new ReplaceValueNode(); found= readReplaceValueNode(str, scNode); - previous->setNextNode(scNode); + if(found) + previous->setNextNode(scNode); } break; case Bind: diff --git a/src/libparser/result/diceresult.cpp b/src/libparser/result/diceresult.cpp index b7e79f9..6f87536 100644 --- a/src/libparser/result/diceresult.cpp +++ b/src/libparser/result/diceresult.cpp @@ -62,7 +62,7 @@ DiceResult::~DiceResult() { if(!m_diceValues.isEmpty()) { - qDeleteAll(m_diceValues.begin(), m_diceValues.end()); + qDeleteAll(m_diceValues); m_diceValues.clear(); } } diff --git a/src/tests/dice/tst_dice.cpp b/src/tests/dice/tst_dice.cpp index f6541d2..2de3bcc 100644 --- a/src/tests/dice/tst_dice.cpp +++ b/src/tests/dice/tst_dice.cpp @@ -496,7 +496,10 @@ void TestDice::scopeDF() auto results= m_diceParser->scalarResultsFromEachInstruction(); for(auto const& result : std::as_const(results)) + { + qDebug() << result; QVERIFY(result >= min && result <= max); + } } void TestDice::scopeDF_data() @@ -1043,7 +1046,7 @@ void TestDice::filterTest_data() QTest::addRow("cmd3") << "[1, 2, 3]f[.>2&:>5]" << 6; QTest::addRow("cmd4") << "[1, 2, 6]f[.<2&>5]" << 6; QTest::addRow("cmd5") << "[2, 2, 6]f[.<2&>5]" << 0; - QTest::addRow("cmd5") << "[1, 5, 1]f[.<2&>5]" << 0; + QTest::addRow("cmd6") << "[1, 5, 1]f[.<2&>5]" << 0; } void TestDice::uniqueTest() @@ -1106,11 +1109,55 @@ void TestDice::spreadTest_data() QTest::addRow("cmd1") << QVector<int>({8, 4, 2}); } -void TestDice::groupTest() {} -void TestDice::groupTest_data() {} +void TestDice::groupTest() +{ + QFETCH(QString, cmd); + QFETCH(int, scalar); + + bool test= m_diceParser->parseLine(cmd); + QVERIFY2(test, cmd.toStdString().c_str()); + + m_diceParser->start(); + + auto results= m_diceParser->scalarResultsFromEachInstruction(); + auto strResult= m_diceParser->finalStringResult([](const QString& result, const QString&, bool) { return result; }); + + QCOMPARE(strResult, QString::number(scalar)); +} +void TestDice::groupTest_data() +{ + QTest::addColumn<QString>("cmd"); + QTest::addColumn<int>("scalar"); + + QTest::addRow("group1") << "[12,7]g5" << 2; + QTest::addRow("group2") << "[12,7,4,3,2,1]g5" << 4; + QTest::addRow("group3") << "[1,1,1,1]g5" << 0; + // QTest::addRow("group4") << "[-18,-2,-1,2]g-3" << 2; +} + +void TestDice::bindTest() +{ + QFETCH(QString, cmd); + QFETCH(int, scalar); + + bool test= m_diceParser->parseLine(cmd); + QVERIFY2(test, cmd.toStdString().c_str()); + + m_diceParser->start(); -void TestDice::bindTest() {} -void TestDice::bindTest_data() {} + auto results= m_diceParser->scalarResultsFromEachInstruction(); + auto strResult= m_diceParser->finalStringResult([](const QString& result, const QString&, bool) { return result; }); + + QCOMPARE(strResult, QString::number(scalar)); +} +void TestDice::bindTest_data() +{ + QTest::addColumn<QString>("cmd"); + QTest::addColumn<int>("scalar"); + + QTest::addRow("bind1") << "[12,7];[18,2]b;$2k2;\"$3\"" << 30; + QTest::addRow("bind2") << "[12,7];[18,2]b;$2k2kl1;\"$3\"" << 12; +} void TestDice::occurenceTest() { |