From df8f29cd113ad1121a4ed41097b4a437a4c7bd12 Mon Sep 17 00:00:00 2001 From: Valentin Noel Date: Thu, 12 Dec 2013 11:37:30 +0100 Subject: [PATCH] add modifications to Checker for repetitions support (and unit test) issue #33 --- .../src/ElementChecker/Checker/Checker.cpp | 67 ++++++--- .../src/ElementChecker/Checker/Checker.hpp | 1 + .../test/checkerTestRepetitions.hpp | 127 ++++++++++++++++++ 3 files changed, 174 insertions(+), 21 deletions(-) diff --git a/libraries/ElementChecker/src/ElementChecker/Checker/Checker.cpp b/libraries/ElementChecker/src/ElementChecker/Checker/Checker.cpp index de3ec83..c9879d6 100644 --- a/libraries/ElementChecker/src/ElementChecker/Checker/Checker.cpp +++ b/libraries/ElementChecker/src/ElementChecker/Checker/Checker.cpp @@ -133,17 +133,22 @@ void Checker::check( const ShPtrElement element ) status = eStatusSkip; } - if( status == eStatusInvalid && ! element->_repetExpr.empty() ) + if( ! element->_repetExpr.empty() ) { LOG_TRACE( "[checker] " << element->_id << " : check repetitions" ); - status = eStatusSkip; std::string errorMessage; - ShPtrElement previous = element->getPrevious(); - if( ! isIterationValid( previous, errorMessage ) ) - { - LOG_ERROR( errorMessage << " (" << element->_id << " )" ); - element->_error.push_back( errorMessage ); + if( status == eStatusValid && ! continueRepetition( element ) ) status = eStatusInvalid; + if( status == eStatusInvalid ) + { + status = eStatusSkip; + ShPtrElement previous = element->getPrevious(); + if( ! isIterationValid( previous, errorMessage ) ) + { + LOG_ERROR( errorMessage << " (" << element->_id << " )" ); + element->_error.push_back( errorMessage ); + status = eStatusInvalid; + } } } @@ -159,20 +164,6 @@ void Checker::check( const ShPtrElement element ) LOG_TRACE( "[checker] " << element->_id << " : return status = " << statusMap.at( status ) ); } -void Checker::setParentGroupSize( const ShPtrElement element ) -{ - ShPtrElement parent = element->getParent(); - - if( parent == nullptr || - element->getPrevious() == nullptr || - element->getSpecNode()->next() != nullptr || - parent->_groupSizeExpr.empty() ) - return; - - parent->_specGroupSize = _exprParser->getExpressionResult< size_t >( parent->_groupSizeExpr ); - LOG_TRACE( "[checker] set " << element->_id << "'s parent (" << parent->_id << ") groupSize (" << parent->_groupSizeExpr << "): " << parent->_specGroupSize ); -} - size_t Checker::getSize( const ShPtrElement element ) { try @@ -218,6 +209,40 @@ size_t Checker::getSize( const ShPtrElement element ) } } +void Checker::setParentGroupSize( const ShPtrElement element ) +{ + ShPtrElement parent = element->getParent(); + + if( parent == nullptr || + element->getPrevious() == nullptr || + element->getSpecNode()->next() != nullptr || + parent->_groupSizeExpr.empty() ) + return; + + parent->_specGroupSize = _exprParser->getExpressionResult< size_t >( parent->_groupSizeExpr ); + LOG_TRACE( "[checker] set " << element->_id << "'s parent (" << parent->_id << ") groupSize (" << parent->_groupSizeExpr << "): " << parent->_specGroupSize ); +} + +bool Checker::continueRepetition( const ShPtrElement element ) +{ + if( element->_repetExpr.empty() ) + return true; + size_t repetMax = 0; + for( std::pair< std::string, std::string > repetPair : element->_repetExpr ) + { + if( repetPair.first != repetPair.second ) + continue; + repetMax = std::max( _exprParser->getExpressionResult< size_t >( repetPair.first ), repetMax ); + } + + if( repetMax != 0 && element->_iteration > repetMax ) + { + LOG_TRACE( "[checker] repetition : " << element->_iteration << " / " << repetMax << ": continue..."); + return false; + } + return true; +} + bool Checker::isIterationValid( const ShPtrElement element, std::string& errorMessage ) { if( element->_repetExpr.empty() ) diff --git a/libraries/ElementChecker/src/ElementChecker/Checker/Checker.hpp b/libraries/ElementChecker/src/ElementChecker/Checker/Checker.hpp index f500656..fe5e2e8 100644 --- a/libraries/ElementChecker/src/ElementChecker/Checker/Checker.hpp +++ b/libraries/ElementChecker/src/ElementChecker/Checker/Checker.hpp @@ -38,6 +38,7 @@ class Checker size_t getSize( const ShPtrElement element ); private: void setParentGroupSize ( const ShPtrElement element ); + bool continueRepetition ( const ShPtrElement element ); bool isIterationValid ( const ShPtrElement element, std::string& errorMessage ); bool isRequirementValid ( const ShPtrElement element ); void checkLastUnorderedElement( const ShPtrElement element ); diff --git a/libraries/ElementChecker/test/checkerTestRepetitions.hpp b/libraries/ElementChecker/test/checkerTestRepetitions.hpp index 0b13e78..6b06b10 100644 --- a/libraries/ElementChecker/test/checkerTestRepetitions.hpp +++ b/libraries/ElementChecker/test/checkerTestRepetitions.hpp @@ -236,6 +236,133 @@ BOOST_AUTO_TEST_CASE( element_checker_checker_repetition ) } } +BOOST_AUTO_TEST_CASE( element_checker_checker_repetition_limited ) +{ + std::string jsonStringBegin = R"*( + { + "content": [ + { + "id": "value1", + "label": "Value1", + "type": "uint16", + "repetition": )*"; + + + std::string jsonStringEnd = R"*( + }, + { + "id": "valueEnd", + "label": "Value End", + "type": "ascii", + "values": "END" + } + ] + } + )*"; + + std::vector< char > buff1 { 0x00, 0x01 }; + std::vector< char > buff2 { 0x00, 0x02 }; + std::vector< char > buff3 { 0x00, 0x03 }; + std::vector< char > buff4 { 'E', 'N', 'D' }; + + LOG_INFO( "\n>>> element_checker_checker_repetition_limited <<<" ); + { + std::string jsonStringRepetition = R"*("3")*"; + + spec_reader::Specification spec; + spec.setFromString( jsonStringBegin + jsonStringRepetition + jsonStringEnd ); + std::shared_ptr< spec_reader::SpecNode > node = spec.getFirstNode(); + BOOST_CHECK_EQUAL( node->getId(), "value1" ); + BOOST_CHECK_EQUAL( node->next()->getId(), "valueEnd" ); + BOOST_CHECK( node->next()->next() == nullptr ); + + Checker checker; + + std::shared_ptr< basic_element::Element > elem1( new basic_element::Element( node ) ); + BOOST_CHECK_EQUAL( elem1->_status, eStatusUnknown ); + elem1->set( buff1, 2 ); + checker.check( elem1 ); + LOG_FATAL( elem1->_id << " | " << typeStringMap.at( elem1->_type ) << " | " << statusMap.at( elem1->_status ) ); + BOOST_CHECK_EQUAL( elem1->_status, eStatusValid ); + + std::shared_ptr< basic_element::Element > elem2( new basic_element::Element( elem1->next(), elem1 ) ); + elem2->set( buff2, 2 ); + checker.check( elem2 ); + LOG_FATAL( elem2->_id << " | " << typeStringMap.at( elem2->_type ) << " | " << statusMap.at( elem2->_status ) ); + BOOST_CHECK_EQUAL( elem2->_status, eStatusValid ); + + std::shared_ptr< basic_element::Element > elem3( new basic_element::Element( elem2->next(), elem2 ) ); + elem3->set( buff3, 2 ); + checker.check( elem3 ); + LOG_FATAL( elem3->_id << " | " << typeStringMap.at( elem3->_type ) << " | " << statusMap.at( elem3->_status ) ); + BOOST_CHECK_EQUAL( elem3->_status, eStatusValid ); + + std::shared_ptr< basic_element::Element > elem4( new basic_element::Element( elem3->next(), elem3 ) ); + elem4->set( buff4, 2 ); + checker.check( elem4 ); + LOG_FATAL( elem4->_id << " | " << typeStringMap.at( elem4->_type ) << " | " << statusMap.at( elem4->_status ) ); + BOOST_CHECK_EQUAL( elem4->_status, eStatusSkip ); + BOOST_CHECK( elem4->_error.empty() ); + + std::shared_ptr< basic_element::Element > elem5( new basic_element::Element( elem4->next(), elem4 ) ); + elem5->set( buff4, 3 ); + checker.check( elem5 ); + BOOST_CHECK_EQUAL( elem5->_status, eStatusValid ); + LOG_FATAL( elem5->_id << " | " << typeStringMap.at( elem5->_type ) << " | " << statusMap.at( elem5->_status ) ); + + BOOST_CHECK( elem5->next() == nullptr ); + } + LOG_INFO( "\n>>> element_checker_checker_repetition_limited suite <<<" ); + { + std::string jsonStringRepetition = R"*( [ + 1, 2, 3 + ] )*"; + + spec_reader::Specification spec; + spec.setFromString( jsonStringBegin + jsonStringRepetition + jsonStringEnd ); + std::shared_ptr< spec_reader::SpecNode > node = spec.getFirstNode(); + BOOST_CHECK_EQUAL( node->getId(), "value1" ); + BOOST_CHECK_EQUAL( node->next()->getId(), "valueEnd" ); + BOOST_CHECK( node->next()->next() == nullptr ); + + Checker checker; + + std::shared_ptr< basic_element::Element > elem1( new basic_element::Element( node ) ); + BOOST_CHECK_EQUAL( elem1->_status, eStatusUnknown ); + elem1->set( buff1, 2 ); + checker.check( elem1 ); + LOG_FATAL( elem1->_id << " | " << typeStringMap.at( elem1->_type ) << " | " << statusMap.at( elem1->_status ) ); + BOOST_CHECK_EQUAL( elem1->_status, eStatusValid ); + + std::shared_ptr< basic_element::Element > elem2( new basic_element::Element( elem1->next(), elem1 ) ); + elem2->set( buff2, 2 ); + checker.check( elem2 ); + LOG_FATAL( elem2->_id << " | " << typeStringMap.at( elem2->_type ) << " | " << statusMap.at( elem2->_status ) ); + BOOST_CHECK_EQUAL( elem2->_status, eStatusValid ); + + std::shared_ptr< basic_element::Element > elem3( new basic_element::Element( elem2->next(), elem2 ) ); + elem3->set( buff3, 2 ); + checker.check( elem3 ); + LOG_FATAL( elem3->_id << " | " << typeStringMap.at( elem3->_type ) << " | " << statusMap.at( elem3->_status ) ); + BOOST_CHECK_EQUAL( elem3->_status, eStatusValid ); + + std::shared_ptr< basic_element::Element > elem4( new basic_element::Element( elem3->next(), elem3 ) ); + elem4->set( buff4, 2 ); + checker.check( elem4 ); + LOG_FATAL( elem4->_id << " | " << typeStringMap.at( elem4->_type ) << " | " << statusMap.at( elem4->_status ) ); + BOOST_CHECK_EQUAL( elem4->_status, eStatusSkip ); + BOOST_CHECK( elem4->_error.empty() ); + + std::shared_ptr< basic_element::Element > elem5( new basic_element::Element( elem4->next(), elem4 ) ); + elem5->set( buff4, 3 ); + checker.check( elem5 ); + BOOST_CHECK_EQUAL( elem5->_status, eStatusValid ); + LOG_FATAL( elem5->_id << " | " << typeStringMap.at( elem5->_type ) << " | " << statusMap.at( elem5->_status ) ); + + BOOST_CHECK( elem5->next() == nullptr ); + } +} + BOOST_AUTO_TEST_CASE( element_checker_checker_repetition_invalid ) { std::string jsonStringBegin = R"*(