From 088259daaeb82986d14af9a28b2feab8a852102f Mon Sep 17 00:00:00 2001 From: Geoffrey Merck Date: Mon, 3 Jan 2022 18:41:55 +0100 Subject: [PATCH] rename test case file and add somre test cases --- ..._parseAPRSFrame_Tests.cpp => APRSFrame.cpp | 39 ++++---- APRSFrame.h | 18 +++- APRSParser.cpp | 76 +++++++++------ APRSParser.h | 6 +- Tests/APRSParser/parseAPRSFrame.cpp | 92 +++++++++++++++++++ 5 files changed, 184 insertions(+), 47 deletions(-) rename Tests/APRSParser/APRSParser_parseAPRSFrame_Tests.cpp => APRSFrame.cpp (54%) create mode 100644 Tests/APRSParser/parseAPRSFrame.cpp diff --git a/Tests/APRSParser/APRSParser_parseAPRSFrame_Tests.cpp b/APRSFrame.cpp similarity index 54% rename from Tests/APRSParser/APRSParser_parseAPRSFrame_Tests.cpp rename to APRSFrame.cpp index 504bc26..70ef101 100644 --- a/Tests/APRSParser/APRSParser_parseAPRSFrame_Tests.cpp +++ b/APRSFrame.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 by Geoffrey Merck F4FXL / KC3FRA + * Copyright (C) 2021-2022 by Geoffrey Merck F4FXL / KC3FRA * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,23 +16,30 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include +#include "APRSFrame.h" -#include "../../APRSParser.h" +CAPRSFrame::CAPRSFrame() : +m_source(), +m_destination(), +m_path(), +m_type(APFT_UNKNOWN) +{ -class APRSParser_parseAPRSFrame_Tests : public ::testing::Test { - -}; +} -TEST_F(APRSParser_parseAPRSFrame_Tests, EmpyString) { +CAPRSFrame::CAPRSFrame(const std::string& source, const std::string& destination, const std::vector& path, APRS_FRAME_TYPE type) : +m_source(source), +m_destination(destination), +m_path(), +m_type(type) +{ + m_path.assign(path.begin(), path.end()); +} - TAPRSFrame aprsFrame; - bool retVal = CAPRSParser::parseFrame("", aprsFrame); - - EXPECT_FALSE(retVal); - EXPECT_STRCASEEQ(aprsFrame.m_body.c_str(), ""); - EXPECT_STRCASEEQ(aprsFrame.m_dest.c_str(), ""); - EXPECT_STRCASEEQ(aprsFrame.m_source.c_str(), ""); - EXPECT_EQ(aprsFrame.m_type, APFT_UNKNOWN); - EXPECT_EQ(aprsFrame.m_path.size(), 0U); +void CAPRSFrame::clear() +{ + m_source.clear(); + m_destination.clear(); + m_path.clear(); + m_type = APFT_UNKNOWN; } \ No newline at end of file diff --git a/APRSFrame.h b/APRSFrame.h index 39494eb..d84a048 100644 --- a/APRSFrame.h +++ b/APRSFrame.h @@ -27,10 +27,22 @@ enum APRS_FRAME_TYPE { APFT_MESSAGE, }; -typedef struct { +class CAPRSFrame { +public: + CAPRSFrame(); + CAPRSFrame(const std::string& source, const std::string& destination, const std::vector& path, APRS_FRAME_TYPE type); + + void clear(); + std::string& getSource() { return m_source; } + std::string& getDestination() { return m_destination; } + std::vector& getPath() { return m_path; } + std::string& getBody() { return m_body; } + APRS_FRAME_TYPE& getType() { return m_type; } + +private: std::string m_source; - std::string m_dest; + std::string m_destination; std::vector m_path; std::string m_body; APRS_FRAME_TYPE m_type; -} TAPRSFrame; \ No newline at end of file +}; \ No newline at end of file diff --git a/APRSParser.cpp b/APRSParser.cpp index d3ed20d..d12076a 100644 --- a/APRSParser.cpp +++ b/APRSParser.cpp @@ -17,42 +17,66 @@ */ #include "APRSParser.h" +#include "Log.h" -bool CAPRSParser::parseFrame(const std::string& frameStr, TAPRSFrame& frame) +bool CAPRSParser::parseFrame(const std::string& frameStr, CAPRSFrame& frame) { - frame.m_body.clear(); - frame.m_dest.clear(); - frame.m_path.clear(); - frame.m_source.clear(); - frame.m_type = APFT_UNKNOWN; + frame.clear(); + bool ret = false; - if(!frameStr.empty()) - return false; + if(!frameStr.empty()) { + auto pos = frameStr.find_first_of(':'); + if(pos != std::string::npos && pos != frameStr.length() - 1) { + auto header = frameStr.substr(0, pos); // contains source, dest and path + auto body = frameStr.substr(pos +1); - auto pos = frameStr.find_first_of(':'); - if(pos == std::string::npos || pos == frameStr.length() - 1) - return false; + std::vector headerSplits; + boost::split(headerSplits, header, [](char c) { return c == ',' || c == '>';}); - auto header = frameStr.substr(0, pos); // contains sours, dest and path - auto body = frameStr.substr(pos +1); + //we need at least source and dest to form a valid frame, also headers shall not contain empty strings + if(headerSplits.size() >= 2 && std::none_of(headerSplits.begin(), headerSplits.end(), [](std::string s){ return s.empty(); })) { + frame.getSource().assign(headerSplits[0]); + frame.getDestination().assign(headerSplits[1]); - std::vector headerSplits; - boost::split(headerSplits, header, [](char c) { return c == ',' || c == '>';}); + for(unsigned int i = 2; i < headerSplits.size(); i++) { + frame.getPath().push_back(headerSplits[i]); + } - if(headerSplits.size() < 2) //we need at least source and dest to form a valid frame - return false; + frame.getBody().assign(body); - frame.m_source.assign(headerSplits[0]); - frame.m_dest.assign(headerSplits[1]); - - for(unsigned int i = 2; i < headerSplits.size(); i++) { - frame.m_path.push_back(headerSplits[i]); + setFrameType(frame); + if(frame.getType() == APFT_UNKNOWN) { + CLog::logInfo("Invalid or unsupported APRS frame : %s", frameStr); + } + else { + ret = true; + } + } + } } - frame.m_body.assign(body); + return ret; +} - frame.m_type = body[0] == ':' ? APFT_MESSAGE : APFT_UNKNOWN; +void CAPRSParser::setFrameType(CAPRSFrame& frame) +{ + APRS_FRAME_TYPE type = APFT_UNKNOWN; + std::string body(frame.getBody()); - return true; -} + if(!body.empty()) { + switch (body[0]) + { + case ':': + if(body[10] == ':') + type = APFT_MESSAGE; + break; + + default: + break; + } + } + frame.getType() = type; + if(type == APFT_UNKNOWN) + frame.clear(); +} \ No newline at end of file diff --git a/APRSParser.h b/APRSParser.h index ede7c2c..6d94f09 100644 --- a/APRSParser.h +++ b/APRSParser.h @@ -26,6 +26,8 @@ class CAPRSParser { public: - //TODO 2022-01-02 move these to own class ? - static bool parseFrame(const std::string& frameStr, TAPRSFrame& frame); + static bool parseFrame(const std::string& frameStr, CAPRSFrame& frame); + +private: + static void setFrameType(CAPRSFrame& frame); }; \ No newline at end of file diff --git a/Tests/APRSParser/parseAPRSFrame.cpp b/Tests/APRSParser/parseAPRSFrame.cpp new file mode 100644 index 0000000..2cb44d7 --- /dev/null +++ b/Tests/APRSParser/parseAPRSFrame.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2021-2022 by Geoffrey Merck F4FXL / KC3FRA + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include "../../APRSParser.h" + +class APRSParser_parseAPRSFrame : public ::testing::Test { + +}; + +TEST_F(APRSParser_parseAPRSFrame, EmpyString) { + + CAPRSFrame aprsFrame; + bool retVal = CAPRSParser::parseFrame("", aprsFrame); + + EXPECT_FALSE(retVal); + EXPECT_STRCASEEQ(aprsFrame.getBody().c_str(), ""); + EXPECT_STRCASEEQ(aprsFrame.getDestination().c_str(), ""); + EXPECT_STRCASEEQ(aprsFrame.getSource().c_str(), ""); + EXPECT_EQ(aprsFrame.getType(), APFT_UNKNOWN); + EXPECT_EQ(aprsFrame.getPath().size(), 0U); +} + +TEST_F(APRSParser_parseAPRSFrame, NoSourceCallsign) { + + CAPRSFrame aprsFrame; + bool retVal = CAPRSParser::parseFrame(">APRS::F4ABC Test Message", aprsFrame); + + EXPECT_FALSE(retVal); + EXPECT_STRCASEEQ(aprsFrame.getBody().c_str(), ""); + EXPECT_STRCASEEQ(aprsFrame.getDestination().c_str(), ""); + EXPECT_STRCASEEQ(aprsFrame.getSource().c_str(), ""); + EXPECT_EQ(aprsFrame.getType(), APFT_UNKNOWN); + EXPECT_EQ(aprsFrame.getPath().size(), 0U); +} + +TEST_F(APRSParser_parseAPRSFrame, NoDestCallsign) { + + CAPRSFrame aprsFrame; + bool retVal = CAPRSParser::parseFrame("N0CALL>::F4ABC Test Message", aprsFrame); + + EXPECT_FALSE(retVal); + EXPECT_STRCASEEQ(aprsFrame.getBody().c_str(), ""); + EXPECT_STRCASEEQ(aprsFrame.getDestination().c_str(), ""); + EXPECT_STRCASEEQ(aprsFrame.getSource().c_str(), ""); + EXPECT_EQ(aprsFrame.getType(), APFT_UNKNOWN); + EXPECT_EQ(aprsFrame.getPath().size(), 0U); +} + +TEST_F(APRSParser_parseAPRSFrame, CorrectMessageFrameWithDigipeater) { + + CAPRSFrame aprsFrame; + bool retVal = CAPRSParser::parseFrame("N0CALL>APRS,WIDE1-1,WIDE2-2::F4ABC :Test Message", aprsFrame); + + EXPECT_TRUE(retVal); + EXPECT_STRCASEEQ(aprsFrame.getBody().c_str(), ":F4ABC :Test Message"); + EXPECT_STRCASEEQ(aprsFrame.getDestination().c_str(), "APRS"); + EXPECT_STRCASEEQ(aprsFrame.getSource().c_str(), "N0CALL"); + EXPECT_EQ(aprsFrame.getType(), APFT_MESSAGE); + EXPECT_EQ(aprsFrame.getPath().size(), 2); + EXPECT_STREQ(aprsFrame.getPath()[0].c_str(), "WIDE1-1"); + EXPECT_STREQ(aprsFrame.getPath()[1].c_str(), "WIDE2-2"); +} + +TEST_F(APRSParser_parseAPRSFrame, CorrectMessageFrameWithoutDigipeater) { + + CAPRSFrame aprsFrame; + bool retVal = CAPRSParser::parseFrame("N0CALL>APRS::F4ABC :Test Message", aprsFrame); + + EXPECT_TRUE(retVal); + EXPECT_STRCASEEQ(aprsFrame.getBody().c_str(), ":F4ABC :Test Message"); + EXPECT_STRCASEEQ(aprsFrame.getDestination().c_str(), "APRS"); + EXPECT_STRCASEEQ(aprsFrame.getSource().c_str(), "N0CALL"); + EXPECT_EQ(aprsFrame.getType(), APFT_MESSAGE); + EXPECT_EQ(aprsFrame.getPath().size(), 0); +} \ No newline at end of file