Files
MuditaOS/module-cellular/test/unittest_URC.cpp
Kuba 091e76ae7c [EGD-6914] Fix missing no sim message
Added QSIMSTAT urc handler and command parser. Added
sim insertion state in SimCard. Now there No Sim response
is sended if sim is missing. Sim not respond timer removed
from Application Manager.
2021-09-09 13:41:08 +02:00

983 lines
33 KiB
C++

// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "Utils.hpp"
#include <algorithm>
#include <cstdint>
#include <string>
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
#include <time/time_conversion.hpp>
#include <time/time_constants.hpp>
#include "UrcQind.hpp"
#include "UrcCusd.hpp"
#include "UrcCtze.hpp"
#include "UrcCreg.hpp"
#include "UrcCmti.hpp"
#include "UrcClip.hpp"
#include "UrcCpin.hpp"
#include "UrcQiurc.hpp"
#include "UrcRing.hpp"
#include "UrcPoweredDown.hpp"
#include "UrcResponse.hpp"
#include <at/UrcQSimstat.hpp>
#include "UrcFactory.hpp"
#include "SimState.hpp"
#include <at/SimInsertedState.hpp>
template <typename urcType> static auto getURC(std::unique_ptr<at::urc::Urc> &urc) -> std::shared_ptr<urcType>
{
if (urc) {
auto &rawUrc = *urc.get();
if (typeid(rawUrc) == typeid(urcType)) {
return std::unique_ptr<urcType>{static_cast<urcType *>(urc.release())};
}
}
return nullptr;
}
TEST_CASE("+Qind: csq")
{
SECTION("CSQ")
{
auto urc = at::urc::UrcFactory::Create("+QIND:\"csq\",100,50");
auto qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE(qind->isCsq());
REQUIRE(*qind->getRSSI() == 100);
REQUIRE(*qind->getBER() == 50);
}
SECTION("CSQ with white spaces")
{
auto urc = at::urc::UrcFactory::Create("+QIND: \"csq\" , 100 , 50 ");
auto qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE(qind->isCsq());
REQUIRE(*qind->getRSSI() == 100);
REQUIRE(*qind->getBER() == 50);
}
SECTION("too short")
{
auto urc = at::urc::UrcFactory::Create("+QIND:\"csq\",100");
auto qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE_FALSE(qind->isCsq());
REQUIRE_FALSE(qind->getRSSI());
REQUIRE_FALSE(qind->getBER());
}
SECTION("too long")
{
auto urc = at::urc::UrcFactory::Create("+QIND:\"csq\",100,50,25");
auto qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE_FALSE(qind->isCsq());
REQUIRE_FALSE(qind->getRSSI());
REQUIRE_FALSE(qind->getBER());
}
SECTION("no integer values")
{
auto urc = at::urc::UrcFactory::Create("+QIND:\"csq\",abc,def");
auto qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE(qind->isCsq());
REQUIRE_FALSE(qind->getRSSI());
REQUIRE_FALSE(qind->getBER());
}
SECTION("not CSQ")
{
auto urc = at::urc::UrcFactory::Create("+QIND:\"qsc\",100,50");
auto qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE_FALSE(qind->isCsq());
REQUIRE_FALSE(qind->getRSSI());
REQUIRE_FALSE(qind->getBER());
}
SECTION("valid CSQ")
{
std::vector<int> vec = {0, 1, 2, 98, 100, 101, 198, 200};
for (auto a : vec) {
auto urc = at::urc::UrcFactory::Create("+QIND:\"csq\"," + std::to_string(a) + ",50");
auto qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE(qind->isCsq());
REQUIRE(*qind->getRSSI() == a);
}
}
SECTION("not valid RSSI")
{
std::vector<std::uint32_t> vec = {99, 199};
for (auto a : vec) {
auto urc = at::urc::UrcFactory::Create("+QIND:\"csq\"," + std::to_string(a) + ",50");
auto qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE(qind->isCsq());
REQUIRE_FALSE(qind->getRSSI());
}
}
SECTION("not valid BER")
{
int ber = 99;
auto urc = at::urc::UrcFactory::Create("+QIND:\"csq\",50," + std::to_string(ber));
auto qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE(qind->isCsq());
REQUIRE(*qind->getRSSI() == 50);
REQUIRE_FALSE(qind->getBER());
}
}
TEST_CASE("+Qind: act")
{
SECTION("ACT")
{
auto urc = at::urc::UrcFactory::Create("+QIND:\"act\",\"HSDPA&HSUPA\"");
auto qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE(qind->isAct());
REQUIRE(qind->getAct() == "HSDPA&HSUPA");
REQUIRE(qind->getAccessTechnology() == Store::Network::AccessTechnology::UtranWHsdpaAndWHsupa);
}
SECTION("too short")
{
auto urc = at::urc::UrcFactory::Create("+QIND:\"act\"");
auto qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE_FALSE(qind->isAct());
REQUIRE(qind->getAct() == "");
REQUIRE(qind->getAccessTechnology() == Store::Network::AccessTechnology::Unknown);
}
SECTION("too long")
{
auto urc = at::urc::UrcFactory::Create("+QIND:\"act\",\"HSDPA&HSUPA\",\"HSDPA&HSUPA\"");
auto qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE_FALSE(qind->isCsq());
REQUIRE(qind->getAct() == "");
REQUIRE(qind->getAccessTechnology() == Store::Network::AccessTechnology::Unknown);
}
SECTION("not act")
{
auto urc = at::urc::UrcFactory::Create("+QIND:\"csq\",\"HSDPA&HSUPA\"");
auto qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE_FALSE(qind->isAct());
REQUIRE(qind->getAct() == "");
REQUIRE(qind->getAccessTechnology() == Store::Network::AccessTechnology::Unknown);
}
SECTION("Uknown NAT")
{
auto urc = at::urc::UrcFactory::Create("+QIND:\"act\",\"Super\"");
auto qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE(qind->isAct());
REQUIRE(qind->getAct() == "Super");
REQUIRE(qind->getAccessTechnology() == Store::Network::AccessTechnology::Unknown);
}
}
TEST_CASE("+Qind: FOTA")
{
SECTION("FOTA")
{
// fota normal
auto urc = at::urc::UrcFactory::Create("+QIND:\"FOTA\",\"HTTPEND\",50");
auto qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE(qind->isFotaValid());
// fota dirty
urc = at::urc::UrcFactory::Create("\r\r\n\n+QIND: \r\n\"FOTA\",\"HTTPEND\",50\n\n\r\r");
qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE(qind->isFotaValid());
}
SECTION("FOTA malformed")
{
auto urc = at::urc::UrcFactory::Create("+QIND:\"FOTA\"");
auto qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE(qind->isFota());
REQUIRE_FALSE(qind->isFotaValid());
}
SECTION("FOTA stage and parameter")
{
auto urc = at::urc::UrcFactory::Create("+QIND: \"FOTA\",\"HTTPSTART\"");
auto qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE(qind->isFota());
REQUIRE(qind->isFotaValid());
REQUIRE(qind->getFotaStage() == at::urc::Qind::FotaStage::HTTPSTART);
REQUIRE(qind->getFotaParameter().empty());
urc = at::urc::UrcFactory::Create("+QIND: \"FOTA\",\"HTTPEND\", 22");
qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE(qind->isFota());
REQUIRE(qind->isFotaValid());
REQUIRE(qind->getFotaStage() == at::urc::Qind::FotaStage::HTTPEND);
REQUIRE(qind->getFotaParameter() == "22");
urc = at::urc::UrcFactory::Create("+QIND: \"FOTA\",\"START\"");
qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE(qind->isFota());
REQUIRE(qind->isFotaValid());
REQUIRE(qind->getFotaStage() == at::urc::Qind::FotaStage::START);
REQUIRE(qind->getFotaParameter().empty());
urc = at::urc::UrcFactory::Create("+QIND: \"FOTA\",\"UPDATING\", 99");
qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE(qind->isFota());
REQUIRE(qind->isFotaValid());
REQUIRE(qind->getFotaStage() == at::urc::Qind::FotaStage::UPDATING);
REQUIRE(qind->getFotaParameter() == "99");
urc = at::urc::UrcFactory::Create("+QIND: \"FOTA\",\"END\", 2");
qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE(qind->isFota());
REQUIRE(qind->isFotaValid());
REQUIRE(qind->getFotaStage() == at::urc::Qind::FotaStage::END);
REQUIRE(qind->getFotaParameter() == "2");
urc = at::urc::UrcFactory::Create("+QIND: \"FOTA\",\"TEST\", 3");
qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE(qind->isFota());
REQUIRE(qind->isFotaValid());
REQUIRE_FALSE(qind->getFotaStage());
REQUIRE(qind->getFotaParameter() == "3");
}
SECTION("FOTA dirty")
{
auto urc =
at::urc::UrcFactory::Create("\n\r+QIND: \n\r\r \"FOTA\" ,\r \n \"HTTPEND\", \n\r test test \r\n");
auto qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE(qind->isFota());
REQUIRE(qind->isFotaValid());
REQUIRE(qind->getFotaStage() == at::urc::Qind::FotaStage::HTTPEND);
REQUIRE(qind->getFotaParameter() == "test test");
}
}
TEST_CASE("+Cusd")
{
SECTION("Cusd action needed")
{
auto urc = at::urc::UrcFactory::Create("+CUSD:1,\"test msg\",14");
auto cusd = getURC<at::urc::Cusd>(urc);
REQUIRE(cusd);
REQUIRE(cusd->isValid());
REQUIRE(cusd->isActionNeeded());
REQUIRE(*cusd->getMessage() == "test msg");
REQUIRE(*cusd->getStatus() == at::urc::Cusd::StatusType::FurtherUserActionRequired);
REQUIRE(*cusd->getDCS() == 14);
}
SECTION("Cusd action needed with white spaces")
{
auto urc = at::urc::UrcFactory::Create("+CUSD: 0 , \"test msg\" , 15 ");
auto cusd = getURC<at::urc::Cusd>(urc);
REQUIRE(cusd);
REQUIRE(cusd->isValid());
REQUIRE_FALSE(cusd->isActionNeeded());
REQUIRE(*cusd->getMessage() == "test msg");
REQUIRE(*cusd->getStatus() == at::urc::Cusd::StatusType::NoFurtherUserActionRequired);
REQUIRE(*cusd->getDCS() == 15);
}
SECTION("Cusd wrong status and DCS")
{
auto urc = at::urc::UrcFactory::Create("+CUSD:100,\"test msg\", abc");
auto cusd = getURC<at::urc::Cusd>(urc);
REQUIRE(cusd);
REQUIRE(cusd->isValid());
REQUIRE_FALSE(cusd->isActionNeeded());
REQUIRE(*cusd->getMessage() == "test msg");
REQUIRE_FALSE(cusd->getStatus());
REQUIRE_FALSE(cusd->getDCS());
}
SECTION("Cusd action not needed")
{
auto urc = at::urc::UrcFactory::Create("+CUSD:2,\"test msg\",15");
auto cusd = getURC<at::urc::Cusd>(urc);
REQUIRE(cusd);
REQUIRE(cusd->isValid());
REQUIRE_FALSE(cusd->isActionNeeded());
}
SECTION("no Cusd")
{
auto urc = at::urc::UrcFactory::Create("+CSUD:1,\"test msg\",15");
auto cusd = getURC<at::urc::Cusd>(urc);
REQUIRE_FALSE(cusd);
}
SECTION("too short")
{
auto urc = at::urc::UrcFactory::Create("+CUSD:1,\"test msg\"");
auto cusd = getURC<at::urc::Cusd>(urc);
REQUIRE(cusd);
REQUIRE_FALSE(cusd->isValid());
}
SECTION("too long")
{
auto urc = at::urc::UrcFactory::Create("+CUSD:1,\"test msg\",15,15");
auto cusd = getURC<at::urc::Cusd>(urc);
REQUIRE(cusd);
REQUIRE_FALSE(cusd->isValid());
}
}
TEST_CASE("+Ctze")
{
SECTION("Not valid data")
{
auto urc = at::urc::UrcFactory::Create("+QIND:\"csq\"");
auto ctze = getURC<at::urc::Ctze>(urc);
REQUIRE_FALSE(ctze);
}
SECTION("ctze +08")
{
auto urc = at::urc::UrcFactory::Create("+CTZE: \"+08\",1,\"2020/10/21,13:49:57\"");
auto ctze = getURC<at::urc::Ctze>(urc);
REQUIRE(ctze);
REQUIRE(ctze->isValid());
auto timeInfo = ctze->getTimeInfo();
std::stringstream ss;
ss << std::put_time(&timeInfo, "%Y/%m/%d,%H:%M:%S");
REQUIRE(ss.str() == "2020/10/21,15:49:57");
REQUIRE(ctze->getTimeZoneOffset() == 8 * utils::time::minutesInQuarterOfHour * utils::time::secondsInMinute);
REQUIRE(ctze->getTimeZoneString() == "+08,1");
ss.str(std::string());
timeInfo = ctze->getGMTTime();
ss << std::put_time(&timeInfo, "%Y/%m/%d,%H:%M:%S");
REQUIRE(ss.str() == "2020/10/21,13:49:57");
}
SECTION("ctze -08")
{
auto urc = at::urc::UrcFactory::Create("+CTZE: \"-08\",1,\"2020/10/21,13:49:57\"");
auto ctze = getURC<at::urc::Ctze>(urc);
REQUIRE(ctze);
REQUIRE(ctze->isValid());
auto timeInfo = ctze->getTimeInfo();
std::ostringstream ss;
ss << std::put_time(&timeInfo, "%Y/%m/%d,%H:%M:%S");
REQUIRE(ss.str() == "2020/10/21,11:49:57");
REQUIRE(ctze->getTimeZoneOffset() == -8 * utils::time::minutesInQuarterOfHour * utils::time::secondsInMinute);
REQUIRE(ctze->getTimeZoneString() == "-08,1");
ss.str(std::string());
timeInfo = ctze->getGMTTime();
ss << std::put_time(&timeInfo, "%Y/%m/%d,%H:%M:%S");
REQUIRE(ss.str() == "2020/10/21,13:49:57");
}
SECTION("ctze -00")
{
auto urc = at::urc::UrcFactory::Create("+CTZE: \"-00\",0,\"2020/10/21,13:49:57\"");
auto ctze = getURC<at::urc::Ctze>(urc);
REQUIRE(ctze);
REQUIRE(ctze->isValid());
auto timeInfo = ctze->getTimeInfo();
std::ostringstream ss;
ss << std::put_time(&timeInfo, "%Y/%m/%d,%H:%M:%S");
REQUIRE(ss.str() == "2020/10/21,13:49:57");
REQUIRE(ctze->getTimeZoneOffset() == 0);
REQUIRE(ctze->getTimeZoneString() == "-00,0");
ss.str(std::string());
timeInfo = ctze->getGMTTime();
ss << std::put_time(&timeInfo, "%Y/%m/%d,%H:%M:%S");
REQUIRE(ss.str() == "2020/10/21,13:49:57");
}
SECTION("too short")
{
auto urc = at::urc::UrcFactory::Create("+CTZE: \"-08\",\"2020/10/21,13:49:57\"");
auto ctze = getURC<at::urc::Ctze>(urc);
REQUIRE(ctze);
REQUIRE_FALSE(ctze->isValid());
// auto timeInfo = ctze->getTimeInfo();
}
}
TEST_CASE("+Creg")
{
SECTION("Creg short")
{
auto urc = at::urc::UrcFactory::Create("+CREG: 0");
auto creg = getURC<at::urc::Creg>(urc);
REQUIRE(creg);
REQUIRE(creg->isValid());
REQUIRE(creg->isShort());
REQUIRE_FALSE(creg->isExtended());
REQUIRE(creg->getStatus() == Store::Network::Status::NotRegistered);
REQUIRE_FALSE(creg->getLocation());
REQUIRE_FALSE(creg->getCellId());
REQUIRE(creg->getAccessTechnology() == Store::Network::AccessTechnology::Unknown);
}
SECTION("Creg extended")
{
auto urc = at::urc::UrcFactory::Create("+CREG: 1,\"D509\",\"80D413D\",7");
auto creg = getURC<at::urc::Creg>(urc);
REQUIRE(creg);
REQUIRE(creg->isValid());
REQUIRE_FALSE(creg->isShort());
REQUIRE(creg->isExtended());
REQUIRE(creg->getStatus() == Store::Network::Status::RegisteredHomeNetwork);
REQUIRE(*creg->getLocation() == "D509");
REQUIRE(*creg->getCellId() == "80D413D");
REQUIRE(creg->getAccessTechnology() == Store::Network::AccessTechnology::EUtran);
}
SECTION("Creg extended access technology")
{
{
auto urc = at::urc::UrcFactory::Create("+CREG: 1,\"D509\",\"80D413D\",0");
auto creg = getURC<at::urc::Creg>(urc);
REQUIRE(creg->getAccessTechnology() == Store::Network::AccessTechnology::Gsm);
}
{
auto urc = at::urc::UrcFactory::Create("+CREG: 1,\"D509\",\"80D413D\",1");
auto creg = getURC<at::urc::Creg>(urc);
REQUIRE(creg->getAccessTechnology() == Store::Network::AccessTechnology::Unknown);
}
{
auto urc = at::urc::UrcFactory::Create("+CREG: 1,\"D509\",\"80D413D\",7");
auto creg = getURC<at::urc::Creg>(urc);
REQUIRE(creg->getAccessTechnology() == Store::Network::AccessTechnology::EUtran);
}
{
auto urc = at::urc::UrcFactory::Create("+CREG: 1,\"D509\",\"80D413D\",8");
auto creg = getURC<at::urc::Creg>(urc);
REQUIRE(creg->getAccessTechnology() == Store::Network::AccessTechnology::Unknown);
}
{
auto urc = at::urc::UrcFactory::Create("+CREG: 1,\"D509\",\"80D413D\",ABX");
auto creg = getURC<at::urc::Creg>(urc);
REQUIRE(creg->getAccessTechnology() == Store::Network::AccessTechnology::Unknown);
}
}
SECTION("Creg status")
{
{
auto urc = at::urc::UrcFactory::Create("+CREG: 0,\"D509\",\"80D413D\",0");
auto creg = getURC<at::urc::Creg>(urc);
REQUIRE(creg->getStatus() == Store::Network::Status::NotRegistered);
}
{
auto urc = at::urc::UrcFactory::Create("+CREG: 5,\"D509\",\"80D413D\",0");
auto creg = getURC<at::urc::Creg>(urc);
REQUIRE(creg->getStatus() == Store::Network::Status::RegisteredRoaming);
}
{
auto urc = at::urc::UrcFactory::Create("+CREG: 4,\"D509\",\"80D413D\",0");
auto creg = getURC<at::urc::Creg>(urc);
REQUIRE(creg->getStatus() == Store::Network::Status::Unknown);
}
{
auto urc = at::urc::UrcFactory::Create("+CREG: 6,\"D509\",\"80D413D\",0");
auto creg = getURC<at::urc::Creg>(urc);
REQUIRE(creg->getStatus() == Store::Network::Status::Unknown);
}
{
auto urc = at::urc::UrcFactory::Create("+CREG: A,\"D509\",\"80D413D\",0");
auto creg = getURC<at::urc::Creg>(urc);
REQUIRE(creg->getStatus() == Store::Network::Status::Unknown);
}
}
SECTION("Creg no Creg")
{
auto urc = at::urc::UrcFactory::Create("+CEGR: 0");
auto creg = getURC<at::urc::Creg>(urc);
REQUIRE_FALSE(creg);
}
SECTION("Creg too short")
{
auto urc = at::urc::UrcFactory::Create("+CREG:");
auto creg = getURC<at::urc::Creg>(urc);
REQUIRE(creg);
REQUIRE_FALSE(creg->isValid());
}
SECTION("Creg too long")
{
auto urc = at::urc::UrcFactory::Create("+CREG: 0,\"D509\",\"80D413D\",0,1");
auto creg = getURC<at::urc::Creg>(urc);
REQUIRE(creg);
REQUIRE_FALSE(creg->isValid());
}
SECTION("Creg wrong length")
{
auto urc = at::urc::UrcFactory::Create("+CREG 0,\"D509\"");
auto creg = getURC<at::urc::Creg>(urc);
REQUIRE(creg);
REQUIRE_FALSE(creg->isValid());
}
}
TEST_CASE("+Cmti")
{
SECTION("Cmti too short")
{
auto urc = at::urc::UrcFactory::Create("+CMTI: \"ME\"");
auto cmti = getURC<at::urc::Cmti>(urc);
REQUIRE(cmti);
REQUIRE_FALSE(cmti->isValid());
}
SECTION("Cmti too long")
{
auto urc = at::urc::UrcFactory::Create("+CMTI: \"ME\",1,1");
auto cmti = getURC<at::urc::Cmti>(urc);
REQUIRE(cmti);
REQUIRE_FALSE(cmti->isValid());
}
SECTION("Cmti valid")
{
auto urc = at::urc::UrcFactory::Create("+CMTI: \"ME\",1");
auto cmti = getURC<at::urc::Cmti>(urc);
REQUIRE(cmti);
REQUIRE(cmti->isValid());
REQUIRE(cmti->getIndex() == "1");
REQUIRE(cmti->getMemory() == "ME");
}
}
TEST_CASE("+CLIP")
{
SECTION("CLIP too short")
{
auto urc = at::urc::UrcFactory::Create("+CLIP: \"+48123456789\"");
auto clip = getURC<at::urc::Clip>(urc);
REQUIRE(clip);
REQUIRE_FALSE(clip->isValid());
}
SECTION("CLIP valid")
{
// two parameters
auto urc = at::urc::UrcFactory::Create("+CLIP: \"+48123456789\",145");
auto clip = getURC<at::urc::Clip>(urc);
REQUIRE(clip);
REQUIRE(clip->isValid());
// three parameters
urc = at::urc::UrcFactory::Create("+CLIP: \"+48123456789\",145,");
clip = getURC<at::urc::Clip>(urc);
REQUIRE(clip);
REQUIRE(clip->isValid());
REQUIRE_FALSE(clip->getSubaddr());
REQUIRE_FALSE(clip->getAlpha());
REQUIRE_FALSE(clip->getSatype());
REQUIRE_FALSE(clip->getCLIValidity());
// four parameters
urc = at::urc::UrcFactory::Create("+CLIP: \"+48123456789\",145,,");
clip = getURC<at::urc::Clip>(urc);
REQUIRE(clip);
REQUIRE(clip->isValid());
REQUIRE_FALSE(clip->getSubaddr());
REQUIRE_FALSE(clip->getAlpha());
REQUIRE_FALSE(clip->getSatype());
REQUIRE_FALSE(clip->getCLIValidity());
// six parameters
urc = at::urc::UrcFactory::Create("+CLIP: \"+48123456789\",145,,,");
clip = getURC<at::urc::Clip>(urc);
REQUIRE(clip);
REQUIRE(clip->isValid());
REQUIRE_FALSE(clip->getSubaddr());
REQUIRE_FALSE(clip->getAlpha());
REQUIRE_FALSE(clip->getSatype());
REQUIRE_FALSE(clip->getCLIValidity());
// seven parameters
urc = at::urc::UrcFactory::Create("+CLIP: \"+48123456789\",145,,,,");
clip = getURC<at::urc::Clip>(urc);
REQUIRE(clip);
REQUIRE(clip->isValid());
REQUIRE_FALSE(clip->getSubaddr());
REQUIRE_FALSE(clip->getAlpha());
REQUIRE_FALSE(clip->getSatype());
REQUIRE_FALSE(clip->getCLIValidity());
// two parameters with validation not empty
urc = at::urc::UrcFactory::Create("+CLIP: \"+48123456789\",145,,,,0");
clip = getURC<at::urc::Clip>(urc);
REQUIRE(clip);
REQUIRE(clip->isValid());
REQUIRE_FALSE(clip->getSubaddr());
REQUIRE_FALSE(clip->getAlpha());
REQUIRE_FALSE(clip->getSatype());
REQUIRE(clip->getCLIValidity() == "0");
}
SECTION("CLIP phone number")
{
auto urc = at::urc::UrcFactory::Create("+CLIP: \"+48123456789\",145,,,,0");
auto clip = getURC<at::urc::Clip>(urc);
REQUIRE(clip);
REQUIRE(clip->isValid());
REQUIRE(clip->getNumber() == "+48123456789");
urc = at::urc::UrcFactory::Create("+CLIP: \"\",145,,,,0");
clip = getURC<at::urc::Clip>(urc);
REQUIRE(clip);
REQUIRE(clip->isValid());
REQUIRE(clip->getNumber() == "");
urc = at::urc::UrcFactory::Create("+CLIP: ,145,,,,0");
clip = getURC<at::urc::Clip>(urc);
REQUIRE(clip);
REQUIRE(clip->isValid());
REQUIRE(clip->getNumber() == "");
}
SECTION("CLIP address type")
{
auto urc = at::urc::UrcFactory::Create("+CLIP: \"+48123456789\",,,,,0");
auto clip = getURC<at::urc::Clip>(urc);
REQUIRE(clip);
REQUIRE(clip->isValid());
REQUIRE_FALSE(clip->getType());
urc = at::urc::UrcFactory::Create("+CLIP: \"+48123456789\",577,,,,0");
clip = getURC<at::urc::Clip>(urc);
REQUIRE(clip);
REQUIRE(clip->isValid());
REQUIRE_FALSE(clip->getType());
urc = at::urc::UrcFactory::Create("+CLIP: \"+48123456789\",\"test\",,,,0");
clip = getURC<at::urc::Clip>(urc);
REQUIRE(clip);
REQUIRE(clip->isValid());
REQUIRE_FALSE(clip->getType());
urc = at::urc::UrcFactory::Create("+CLIP: \"+48123456789\",test,,,,0");
clip = getURC<at::urc::Clip>(urc);
REQUIRE(clip);
REQUIRE(clip->isValid());
REQUIRE_FALSE(clip->getType());
urc = at::urc::UrcFactory::Create("+CLIP: \"+48123456789\",129,,,,0");
clip = getURC<at::urc::Clip>(urc);
REQUIRE(clip);
REQUIRE(clip->isValid());
REQUIRE(clip->getType() == at::urc::Clip::AddressType::UnknownType);
urc = at::urc::UrcFactory::Create("+CLIP: \"+48123456789\",145,,,,0");
clip = getURC<at::urc::Clip>(urc);
REQUIRE(clip);
REQUIRE(clip->isValid());
REQUIRE(clip->getType() == at::urc::Clip::AddressType::InternationalNumber);
urc = at::urc::UrcFactory::Create("+CLIP: \"+48123456789\",161,,,,0");
clip = getURC<at::urc::Clip>(urc);
REQUIRE(clip);
REQUIRE(clip->isValid());
REQUIRE(clip->getType() == at::urc::Clip::AddressType::NationalNumber);
}
SECTION("CLIP optional parameters")
{
auto urc = at::urc::UrcFactory::Create("+CLIP: \"+48123456789\",145,,,,");
auto clip = getURC<at::urc::Clip>(urc);
REQUIRE(clip);
REQUIRE(clip->isValid());
REQUIRE_FALSE(clip->getAlpha());
REQUIRE_FALSE(clip->getSatype());
REQUIRE_FALSE(clip->getSubaddr());
REQUIRE_FALSE(clip->getCLIValidity());
urc = at::urc::UrcFactory::Create("+CLIP: \"+48123456789\",145,1,2,3,0");
clip = getURC<at::urc::Clip>(urc);
REQUIRE(clip);
REQUIRE(clip->isValid());
REQUIRE(clip->getAlpha() == "3");
REQUIRE(clip->getSatype() == "2");
REQUIRE(clip->getSubaddr() == "1");
REQUIRE(clip->getCLIValidity() == "0");
}
}
TEST_CASE("+CPIN")
{
SECTION("CPIN supported")
{
auto urc = at::urc::UrcFactory::Create("+CPIN: SIM PIN");
auto cpin = getURC<at::urc::Cpin>(urc);
REQUIRE(cpin);
REQUIRE(cpin->isValid());
REQUIRE(cpin->getState() == at::SimState::SimPin);
REQUIRE(cpin->getMessage() == "SIM PIN");
}
SECTION("CPIN not supported")
{
auto urc = at::urc::UrcFactory::Create("+CPIN: \"Unknown\"");
auto cpin = getURC<at::urc::Cpin>(urc);
REQUIRE(cpin);
REQUIRE(cpin->getState() == at::SimState::Unknown);
}
}
TEST_CASE("POWERED DOWN")
{
SECTION("POWERED DOWN valid")
{
auto urc = at::urc::UrcFactory::Create("POWERED DOWN");
auto pwd = getURC<at::urc::PoweredDown>(urc);
REQUIRE(pwd);
REQUIRE(pwd->isValid());
REQUIRE(pwd->isImmediatePowerDown());
REQUIRE_FALSE(pwd->isNormalPowerDown());
urc = at::urc::UrcFactory::Create("NORMAL POWER DOWN");
pwd = getURC<at::urc::PoweredDown>(urc);
REQUIRE(pwd);
REQUIRE(pwd->isValid());
REQUIRE_FALSE(pwd->isImmediatePowerDown());
REQUIRE(pwd->isNormalPowerDown());
// dirty
urc = at::urc::UrcFactory::Create("\n\r POWERED DOWN\n\r ");
pwd = getURC<at::urc::PoweredDown>(urc);
REQUIRE(pwd);
REQUIRE(pwd->isValid());
REQUIRE(pwd->isImmediatePowerDown());
REQUIRE_FALSE(pwd->isNormalPowerDown());
urc = at::urc::UrcFactory::Create(" \n\r NORMAL POWER DOWN \n\r ");
pwd = getURC<at::urc::PoweredDown>(urc);
REQUIRE(pwd);
REQUIRE(pwd->isValid());
REQUIRE_FALSE(pwd->isImmediatePowerDown());
REQUIRE(pwd->isNormalPowerDown());
}
SECTION("POWERED DOWN invalid")
{
auto pwd = at::urc::PoweredDown("TEST");
REQUIRE_FALSE(pwd.isValid());
REQUIRE_FALSE(pwd.isImmediatePowerDown());
REQUIRE_FALSE(pwd.isNormalPowerDown());
}
}
TEST_CASE("Urc RESPONSE")
{
SECTION("Urc RESPONSE valid")
{
auto urc = at::urc::UrcFactory::Create("OK");
auto rsp = getURC<at::urc::UrcResponse>(urc);
REQUIRE(rsp);
REQUIRE(rsp->getURCResponseType() == at::urc::UrcResponse::URCResponseType::Ok);
urc = at::urc::UrcFactory::Create("CONNECT");
rsp = getURC<at::urc::UrcResponse>(urc);
REQUIRE(rsp);
REQUIRE(rsp->getURCResponseType() == at::urc::UrcResponse::URCResponseType::Connect);
urc = at::urc::UrcFactory::Create("NO CARRIER");
rsp = getURC<at::urc::UrcResponse>(urc);
REQUIRE(rsp);
REQUIRE(rsp->getURCResponseType() == at::urc::UrcResponse::URCResponseType::NoCarrier);
urc = at::urc::UrcFactory::Create("ERROR");
rsp = getURC<at::urc::UrcResponse>(urc);
REQUIRE(rsp);
REQUIRE(rsp->getURCResponseType() == at::urc::UrcResponse::URCResponseType::Error);
urc = at::urc::UrcFactory::Create("NO DIALTONE");
rsp = getURC<at::urc::UrcResponse>(urc);
REQUIRE(rsp);
REQUIRE(rsp->getURCResponseType() == at::urc::UrcResponse::URCResponseType::NoDialtone);
urc = at::urc::UrcFactory::Create("BUSY");
rsp = getURC<at::urc::UrcResponse>(urc);
REQUIRE(rsp);
REQUIRE(rsp->getURCResponseType() == at::urc::UrcResponse::URCResponseType::Busy);
urc = at::urc::UrcFactory::Create("NO ANSWER");
rsp = getURC<at::urc::UrcResponse>(urc);
REQUIRE(rsp);
REQUIRE(rsp->getURCResponseType() == at::urc::UrcResponse::URCResponseType::NoAnswer);
}
SECTION("Urc RESPONSE dirty")
{
auto urc = at::urc::UrcFactory::Create("\n\n \rNO ANSWER\n\r\n");
auto rsp = getURC<at::urc::UrcResponse>(urc);
REQUIRE(rsp);
REQUIRE(rsp->getURCResponseType() == at::urc::UrcResponse::URCResponseType::NoAnswer);
}
}
TEST_CASE("+Qind: SMS DONE")
{
SECTION("SMS DONE")
{
// SMS DONE normal
auto urc = at::urc::UrcFactory::Create("+QIND: SMS DONE");
auto qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE(qind->isSmsDone());
// SMS DONE dirty
urc = at::urc::UrcFactory::Create("\r\r\n\n+QIND: SMS DONE\n\n\r\r");
qind = getURC<at::urc::Qind>(urc);
REQUIRE(qind);
REQUIRE(qind->isSmsDone());
}
}
TEST_CASE("+Qiurc: TCP Context and connection message")
{
SECTION("PDP Context deactivate - normal message")
{
/// +QIURC:"pdpdeact",<contextID>
auto urc = at::urc::UrcFactory::Create("+QIURC: \"pdpdeact\",1");
auto qiurc = getURC<at::urc::Qiurc>(urc);
REQUIRE(qiurc);
REQUIRE(qiurc->getType());
REQUIRE(qiurc->isValid());
REQUIRE(*qiurc->getType() == at::urc::Qiurc::QIUrcMessages::DeactivateContext);
REQUIRE(*qiurc->getFirstParam() == "1");
}
SECTION("PDP Context deactivate - corrupted, but OK format")
{
auto urc = at::urc::UrcFactory::Create("+QIURC:\"pdpdeactwww\",1");
auto qiurc = getURC<at::urc::Qiurc>(urc);
REQUIRE(qiurc);
REQUIRE(qiurc->getType() == std::nullopt);
}
SECTION("PDP Context deactivate - wrong param count (in case simple implementation)")
{
auto urc = at::urc::UrcFactory::Create("+QIURC:\"pdpdeactwww\",1,3");
auto qiurc = getURC<at::urc::Qiurc>(urc);
REQUIRE(qiurc->getType() == std::nullopt);
}
}
TEST_CASE("RING")
{
struct RingTest
{
std::string body;
std::optional<at::urc::Ring::RingType> ringType;
};
std::vector<RingTest> testCases = {
{"RING", at::urc::Ring::Normal},
{"+CRING: ASYNC", at::urc::Ring::Async},
{"+CRING: SYNC", at::urc::Ring::Sync},
{"+CRING: REL ASYNC", at::urc::Ring::RelAsync},
{"\r\n+CRING: REL SYNC", at::urc::Ring::RelSync},
{"+CRING: FAX", at::urc::Ring::Fax},
{"+CRING: VOICE", at::urc::Ring::Voice},
{"+CRING: BUMMER", std::nullopt},
};
for (auto &test : testCases) {
auto urc = at::urc::UrcFactory::Create(test.body);
auto ring = getURC<at::urc::Ring>(urc);
REQUIRE(ring);
if (test.ringType) {
REQUIRE(ring->getType());
REQUIRE(ring->getType().value() == test.ringType);
}
else {
REQUIRE(!ring->isValid());
REQUIRE(!ring->getType());
}
}
}
TEST_CASE("QSimstat")
{
SECTION("Valid parameter, inserted")
{
auto urc = at::urc::UrcFactory::Create("+QSIMSTAT: 1,1");
auto qsimstat = getURC<at::urc::QSimstat>(urc);
REQUIRE(qsimstat);
REQUIRE(qsimstat->getInsertedStatus() == at::SimInsertedStatus::Inserted);
REQUIRE(qsimstat->getEnabled() == at::SimInsertedStatusEnable::Enable);
}
SECTION("Valid parameter, removed")
{
auto urc = at::urc::UrcFactory::Create("+QSIMSTAT: 1,0");
auto qsimstat = getURC<at::urc::QSimstat>(urc);
REQUIRE(qsimstat);
REQUIRE(qsimstat->getInsertedStatus() == at::SimInsertedStatus::Removed);
REQUIRE(qsimstat->getEnabled() == at::SimInsertedStatusEnable::Enable);
}
SECTION("Valid parameter, unknown")
{
auto urc = at::urc::UrcFactory::Create("+QSIMSTAT: 0,2");
auto qsimstat = getURC<at::urc::QSimstat>(urc);
REQUIRE(qsimstat);
REQUIRE(qsimstat->getInsertedStatus() == at::SimInsertedStatus::Unknown);
REQUIRE(qsimstat->getEnabled() == at::SimInsertedStatusEnable::Disable);
}
SECTION("Invalid parameter, wrong Enable token")
{
auto urc = at::urc::UrcFactory::Create("+QSIMSTAT: 5,2");
auto qsimstat = getURC<at::urc::QSimstat>(urc);
REQUIRE(qsimstat);
REQUIRE(qsimstat->getInsertedStatus() == at::SimInsertedStatus::Unknown);
REQUIRE(qsimstat->getEnabled() == std::nullopt);
}
SECTION("Invalid parameter, wrong Inserted Status token")
{
auto urc = at::urc::UrcFactory::Create("+QSIMSTAT: 0,7");
auto qsimstat = getURC<at::urc::QSimstat>(urc);
REQUIRE(qsimstat);
REQUIRE(qsimstat->getInsertedStatus() == std::nullopt);
REQUIRE(qsimstat->getEnabled() == at::SimInsertedStatusEnable::Disable);
}
}