// // Copyright (C) 2020 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #include #include "common/libs/fs/shared_select.h" #include "common/libs/utils/files.h" #include "host/commands/assemble_cvd/flags_defaults.h" #include "host/commands/modem_simulator/channel_monitor.h" #include "host/commands/modem_simulator/device_config.h" #include "host/commands/modem_simulator/modem_simulator.h" #include "host/libs/config/cuttlefish_config.h" namespace fs = std::filesystem; static const char *myiccfile = #include "iccfile.txt" ; static const std::string tmp_test_dir = std::string(fs::temp_directory_path()) + std::string("/cuttlefish_modem_test"); using namespace cuttlefish; class ModemServiceTest : public ::testing::Test { protected: static void SetUpTestSuite() { { cuttlefish::CuttlefishConfig tmp_config_obj; std::string config_file = tmp_test_dir + "/.cuttlefish_config.json"; tmp_config_obj.set_root_dir(tmp_test_dir + "/cuttlefish"); std::vector instance_nums; for (int i = 0; i < 1; i++) { instance_nums.push_back(cuttlefish::GetInstance() + i); } for (const auto &num : instance_nums) { auto instance = tmp_config_obj.ForInstance(num); // Trigger creation in map instance.set_ril_dns(CF_DEFAULTS_RIL_DNS); } for (auto instance : tmp_config_obj.Instances()) { fs::create_directories(instance.instance_dir()); if (!tmp_config_obj.SaveToFile( instance.PerInstancePath("cuttlefish_config.json"))) { LOG(ERROR) << "Unable to save copy config object"; return; } std::string icfilename = instance.PerInstancePath("/iccprofile_for_sim0.xml"); std::ofstream offile = modem::DeviceConfig::open_ofstream_crossplat(icfilename.c_str(), std::ofstream::out); offile << std::string(myiccfile); offile.close(); fs::copy_file(instance.PerInstancePath("/cuttlefish_config.json"), config_file, fs::copy_options::overwrite_existing); } ::setenv("CUTTLEFISH_CONFIG_FILE", config_file.c_str(), 1); } cuttlefish::SharedFD ril_shared_fd, modem_shared_fd; if (!SharedFD::SocketPair(AF_LOCAL, SOCK_STREAM, 0, &ril_shared_fd, &modem_shared_fd)) { LOG(ERROR) << "Unable to create client socket pair: " << strerror(errno); } ASSERT_TRUE(ril_shared_fd->IsOpen()); ASSERT_TRUE(modem_shared_fd->IsOpen()); NvramConfig::InitNvramConfigService(1, 1); ril_side_ = new Client(ril_shared_fd); modem_side_ = new Client(modem_shared_fd); modem_simulator_ = new ModemSimulator(0); cuttlefish::SharedFD server; auto channel_monitor = std::make_unique(*modem_simulator_, server); modem_simulator_->Initialize(std::move(channel_monitor)); } static void TearDownTestSuite() { delete ril_side_; delete modem_side_; delete modem_simulator_; fs::remove_all(tmp_test_dir); }; void SendCommand(std::string command, std::string prefix = "") { command_prefix_ = prefix; modem_simulator_->DispatchCommand(*modem_side_, command); } void ReadCommandResponse(std::vector& response) { do { std::vector buffer(4096); // kMaxCommandLength auto bytes_read = ril_side_->client_read_fd_->Read(buffer.data(), buffer.size()); if (bytes_read <= 0) { // Close here to ensure the other side gets reset if it's still // connected ril_side_->client_read_fd_->Close(); ril_side_->client_write_fd_->Close(); LOG(WARNING) << "Detected close from the other side"; break; } std::string& incomplete_command = ril_side_->incomplete_command; // Add the incomplete command from the last read auto commands = std::string{incomplete_command.data()}; commands.append(buffer.data()); incomplete_command.clear(); incomplete_command.resize(0); // replacing '\n' with '\r' commands = android::base::StringReplace(commands, "\n", "\r", true); // split into commands and dispatch size_t pos = 0, r_pos = 0; // '\r' or '\n' while (r_pos != std::string::npos) { r_pos = commands.find('\r', pos); if (r_pos != std::string::npos) { auto command = commands.substr(pos, r_pos - pos); if (command.size() > 0) { // "\r\r" ? LOG(DEBUG) << "AT< " << command; if (IsFinalResponseSuccess(command) || IsFinalResponseError(command)) { response.push_back(command); return; } else if (IsIntermediateResponse(command)) { response.push_back(command); } else { ; // Ignore unsolicited command } } pos = r_pos + 1; // skip '\r' } else if (pos < commands.length()) { // incomplete command incomplete_command = commands.substr(pos); LOG(VERBOSE) << "incomplete command: " << incomplete_command; } } } while (true); // read response } inline bool IsFinalResponseSuccess(std::string response) { auto iter = kFinalResponseSuccess.begin(); for (; iter != kFinalResponseSuccess.end(); ++iter) { if (*iter == response) { return true; } } return false; } inline bool IsFinalResponseError(std::string response) { auto iter = kFinalResponseError.begin(); for (; iter != kFinalResponseError.end(); ++iter) { if (response.compare(0, iter->size(), *iter) == 0) { return true; } } return false; } inline bool IsIntermediateResponse(std::string response) { if (response.compare(0, command_prefix_.size(), command_prefix_) == 0) { return true; } return false; } int openLogicalChannel(std::string& name) { // Create and send command std::string command = "AT+CCHO="; command.append(name); std::vector response; SendCommand(command); ReadCommandResponse(response); int channel = std::stoi(response[0]); return channel; } bool closeLogicalChannel(int channel) { std::string command = "AT+CCHC="; command += std::to_string(channel); std::vector response; SendCommand(command); ReadCommandResponse(response); std::string expect = "+CCHC"; return (response[0].compare(0, expect.size(), expect) == 0); } const std::vector kFinalResponseSuccess = {"OK", "CONNECT", "> "}; const std::vector kFinalResponseError = { "ERROR", "+CMS ERROR:", "+CME ERROR:", "NO CARRIER", /* sometimes! */ "NO ANSWER", "NO DIALTONE", }; static Client* ril_side_; static Client* modem_side_; static ModemSimulator* modem_simulator_; // For distinguishing the response from command response or unsolicited command std::string command_prefix_; }; ModemSimulator* ModemServiceTest::modem_simulator_ = nullptr; Client* ModemServiceTest::ril_side_ = nullptr; Client* ModemServiceTest::modem_side_ = nullptr; /* Sim Service Test */ TEST_F(ModemServiceTest, GetIccCardStatus) { const char *expects[] = {"+CPIN: READY", "OK"}; std::string command = "AT+CPIN?"; std::vector response; SendCommand(command, "+CPIN:"); ReadCommandResponse(response); ASSERT_EQ(response.size(), 2); ASSERT_STREQ(response[0].c_str(), expects[0]); ASSERT_STREQ(response[1].c_str(), expects[1]); } TEST_F(ModemServiceTest, ChangeOrEnterPIN) { std::vector commands = {"AT+CPIN=1234,0000", "AT+CPIN=1111,2222",}; std::vector expects = {"OK", "+CME ERROR: 16",}; std::vector response; auto expects_iter = expects.begin(); for (auto iter = commands.begin(); iter != commands.end(); ++iter, ++expects_iter) { SendCommand(*iter); ReadCommandResponse(response); ASSERT_STREQ(response[0].c_str(), (*expects_iter).c_str()); response.clear(); } } TEST_F(ModemServiceTest, SIM_IO) { std::vector commands = {"AT+CRSM=192,12258,0,0,15", "AT+CRSM=192,28436,0,0,15", "AT+CRSM=220,28618,1,4,5,0000000000"}; std::vector expects = {"+CRSM: 144,0,62178202412183022FE28A01058B032F06038002000A880110", "+CRSM: 106,130", "+CRSM: 144,0"}; std::vector response; auto expects_iter = expects.begin(); for (auto iter = commands.begin(); iter != commands.end(); ++iter, ++expects_iter) { SendCommand(*iter); ReadCommandResponse(response); ASSERT_EQ(response.size(), 2); ASSERT_STREQ(response[0].c_str(), (*expects_iter).c_str()); response.clear(); } } TEST_F(ModemServiceTest, GetIMSI) { std::string command = "AT+CIMI"; std::vector response; SendCommand(command); ReadCommandResponse(response); ASSERT_EQ(response.size(), 2); const char *expect = "460110031689666"; ASSERT_STREQ(response[0].c_str(),expect); } TEST_F(ModemServiceTest, GetIccId) { std::string command = "AT+CICCID"; std::vector response; SendCommand(command); ReadCommandResponse(response); ASSERT_EQ(response.size(), 2); const char *expect = "89860318640220133897"; ASSERT_STREQ(response[0].c_str(),expect); } TEST_F(ModemServiceTest, FacilityLock) { std::vector commands = { "AT+CLCK=\"FD\",2,"",7", "AT+CLCK=\"SC\",2,"",7", "AT+CLCK=\"SC\",1,\"1234\",7", "AT+CLCK=\"SC\",1,\"023000\",7" }; std::vector expects = { "+CLCK: 0", "+CLCK: 0", "+CME ERROR: 16", "+CME ERROR: 16" }; std::vector response; auto expects_iter = expects.begin(); for (auto iter = commands.begin(); iter != commands.end(); ++iter, ++expects_iter) { SendCommand(*iter); ReadCommandResponse(response); ASSERT_STREQ(response[0].c_str(), (*expects_iter).c_str()); response.clear(); } } TEST_F(ModemServiceTest, OpenLogicalChannel) { std::string command= "A000000063504B43532D3135"; int firstChannel = openLogicalChannel(command); ASSERT_EQ(firstChannel, 1); command= "A000000063504B43532D3135"; int secondChannel = openLogicalChannel(command); ASSERT_GE(secondChannel, 1); closeLogicalChannel(firstChannel); closeLogicalChannel(secondChannel); } TEST_F(ModemServiceTest, CloseLogicalChannel) { std::string command= "A000000063504B43532D3135"; int channel = openLogicalChannel(command); ASSERT_EQ(channel, 1); ASSERT_FALSE(closeLogicalChannel(channel + 3)); ASSERT_TRUE(closeLogicalChannel(channel)); } TEST_F(ModemServiceTest, TransmitLogicalChannel) { std::string command= "A000000063504B43532D3135"; int channel = openLogicalChannel(command); ASSERT_EQ(channel, 1); command = "AT+CGLA="; command += channel; command += ",10,80caff4000"; std::vector response; SendCommand(command); ReadCommandResponse(response); const char *expect = "+CME ERROR: 21"; ASSERT_STREQ(response[0].c_str(),expect); ASSERT_TRUE(closeLogicalChannel(channel)); } /* Network Service Test */ TEST_F(ModemServiceTest, testRadioPowerReq) { std::string command = "AT+CFUN?"; std::vector response; SendCommand(command, "+CFUN:"); ReadCommandResponse(response); ASSERT_EQ(response.size(), 2); ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, testSetRadioPower) { std::string command = "AT+CFUN=1"; std::vector response; SendCommand(command); ReadCommandResponse(response); ASSERT_EQ(response.size(), 1); ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, testSignalStrength) { std::string command = "AT+CSQ"; std::vector response; SendCommand(command, "+CSQ:"); ReadCommandResponse(response); ASSERT_EQ(response.size(), 2); ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, testQueryNetworkSelectionMode) { std::string command = "AT+COPS?"; std::vector response; SendCommand(command, "+COPS:"); ReadCommandResponse(response); ASSERT_EQ(response.size(), 2); ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, testRequestOperator) { std::string command = "AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?"; std::vector response; SendCommand(command, "+COPS:"); ReadCommandResponse(response); ASSERT_EQ(response.size(), 4); } TEST_F(ModemServiceTest, testVoiceNetworkRegistration) { std::string command = "AT+CREG?"; std::vector response; SendCommand(command, "+CREG:"); ReadCommandResponse(response); ASSERT_EQ(response.size(), 2); ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, testDataNetworkRegistration) { std::string command = "AT+CGREG?"; std::vector response; SendCommand(command, "+CGREG:"); ReadCommandResponse(response); ASSERT_EQ(response.size(), 2); ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, testDataNetworkRegistrationWithLte2) { std::string command = "AT+CEREG?"; std::vector response; SendCommand(command, "+CEREG:"); ReadCommandResponse(response); ASSERT_EQ(response.size(), 2); ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, testGetPreferredNetworkType) { std::string command = "AT+CTEC?"; std::vector response; SendCommand(command, "+CTEC:"); ReadCommandResponse(response); ASSERT_EQ(response.size(), 2); ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, testQuerySupportedTechs) { std::string command = "AT+CTEC=?"; std::vector response; SendCommand(command, "+CTEC:"); ReadCommandResponse(response); ASSERT_EQ(response.size(), 2); ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, testSetPreferredNetworkType) { std::string command = "AT+CTEC=1,\"201\""; std::vector response; SendCommand(command, "+CTEC:"); ReadCommandResponse(response); ASSERT_EQ(response.size(), 2); ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str()); } /* Call Service Test */ TEST_F(ModemServiceTest, testCurrentCalls) { std::string command = "AT+CLCC"; std::vector response; SendCommand(command, "+CLCC:"); ReadCommandResponse(response); ASSERT_EQ(response.size(), 1); } TEST_F(ModemServiceTest, testHangup) { for (int i = 0; i < 5; i ++) { std::stringstream ss; ss.clear(); ss << "AT+CHLD=" << i; SendCommand(ss.str()); } std::vector response; ReadCommandResponse(response); ASSERT_EQ(response.size(), 1); ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, testMute) { std::string command = "AT+CMUT=1"; std::vector response; SendCommand(command); ReadCommandResponse(response); ASSERT_EQ(response.size(), 1); ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, testSendDtmf) { std::string command = "AT+VTS=1"; std::vector response; SendCommand(command); ReadCommandResponse(response); ASSERT_EQ(response.size(), 1); ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, testExitEmergencyMode) { std::string command = "AT+WSOS=0"; std::vector response; SendCommand(command); ReadCommandResponse(response); ASSERT_EQ(response.size(), 1); ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str()); } /* Data Service Test */ TEST_F(ModemServiceTest, SetPDPContext) { std::string command = "AT+CGDCONT=1,\"IPV4V6\",\"ctlte\",,0,0"; std::vector response; SendCommand(command); ReadCommandResponse(response); ASSERT_EQ(response.size(), 1); ASSERT_STREQ(response.at(0).c_str(), kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, QueryPDPContextList) { for (int i = 1; i < 5; i ++) { std::stringstream ss; ss.clear(); ss << "AT+CGDCONT=" << i << ",\"IPV4V6\",\"ctlte\",,0,0"; SendCommand(ss.str()); } std::string command = "AT+CGDCONT?"; std::vector response; SendCommand(command, "+CGDCONT:"); ReadCommandResponse(response); const char *result = response[response.size() - 1].c_str(); ASSERT_EQ(response.size(), 1); ASSERT_STREQ(result, kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, ActivateDataCall) { std::string command = "AT+CGACT= 1,0"; std::vector response; SendCommand(command); ReadCommandResponse(response); const char *result = response[0].c_str(); ASSERT_STREQ(result, kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, QueryDataCallList) { std::string command = "AT+CGACT?"; std::vector response; SendCommand(command, "+CGACT:"); ReadCommandResponse(response); const char *result = response[response.size() - 1].c_str(); ASSERT_STREQ(result, kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, ReadDynamicParamTrue) { std::string command = "AT+CGCONTRDP=1"; std::vector response; SendCommand(command); ReadCommandResponse(response); const char *result = response[response.size() - 1].c_str(); ASSERT_STREQ(result, kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, ReadDynamicParamFalse) { std::string command = "AT+CGCONTRDP=10"; std::vector response; SendCommand(command); ReadCommandResponse(response); const char *result = response[response.size() - 1].c_str(); const char *expect = "+CME ERROR: 21"; ASSERT_STREQ(result, expect); } TEST_F(ModemServiceTest, EnterDataState) { std::string command = "AT+CGDATA=1,1"; std::vector response; SendCommand(command); ReadCommandResponse(response); const char *result = response[response.size() - 1].c_str(); ASSERT_STREQ(result, kFinalResponseSuccess[1].c_str()); } /* SMS Service Test */ TEST_F(ModemServiceTest, SendSMS) { std::string command = "AT+CMGS=35"; std::vector response; SendCommand(command); ReadCommandResponse(response); const char *result = response[response.size() - 1].c_str(); const char *expect = "> "; ASSERT_STREQ(result, expect); command = "0001000D91688118109844F0000017AFD7903AB55A9BBA69D639D4ADCBF99E3DCCAE9701^Z"; //command += '\032'; SendCommand(command); ReadCommandResponse(response); // TODO (bohu) for some reason the following asserts fail, fix them // ASSERT_EQ(response.size(), 3); // ASSERT_STREQ(response[response.size() - 1].c_str(), // kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, WriteSMSToSim) { std::string command = "AT+CMGW=24,3"; std::vector response; SendCommand(command); ReadCommandResponse(response); const char *result = response[response.size() - 1].c_str(); const char *expect = "> "; ASSERT_STREQ(result, expect); command = "00240B815123106351F100000240516054410005C8329BFD06^Z"; SendCommand(command); ReadCommandResponse(response); ASSERT_EQ(response.size(), 3); ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, SMSAcknowledge) { std::string command = "AT+CNMA=1"; std::vector response; SendCommand(command); ReadCommandResponse(response); const char *result = response[response.size() - 1].c_str(); ASSERT_STREQ(result, kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, DeleteSmsOnSimTure) { std::string command = "AT+CMGD=1"; std::vector response; SendCommand(command); ReadCommandResponse(response); const char *result = response[0].c_str(); ASSERT_STREQ(result, kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, DeleteSmsOnSimFalse) { std::string command = "AT+CMGD=1"; std::vector response; SendCommand(command); ReadCommandResponse(response); const char *result = response[0].c_str(); const char *expect = "+CME ERROR: 21"; ASSERT_STREQ(result, expect); } TEST_F(ModemServiceTest, SetBroadcastConfig) { std::string command = "AT+CSCB=0,\"4356\",\"0-255\""; std::vector response; SendCommand(command); ReadCommandResponse(response); const char *result = response[0].c_str(); ASSERT_STREQ(result, kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, GetBroadcastConfig) { std::string command = "AT+CSCB?"; std::vector response; SendCommand(command); ReadCommandResponse(response); ASSERT_EQ(response.size(), 2); const char *result = response[response.size() - 1].c_str(); ASSERT_STREQ(result, kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, SetSmscAddress) { std::string command = "AT+CSCA=\"91688115667566F4\",16"; std::vector response; SendCommand(command); ReadCommandResponse(response); ASSERT_EQ(response.size(), 1); const char *result = response[response.size() - 1].c_str(); ASSERT_STREQ(result, kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, GetSmscAddress) { std::string command = "AT+CSCA?"; std::vector response; SendCommand(command); ReadCommandResponse(response); ASSERT_EQ(response.size(), 2); const char *result = response[response.size() - 1].c_str(); ASSERT_STREQ(result, kFinalResponseSuccess[0].c_str()); } /* SUP Service Test */ TEST_F(ModemServiceTest, testUSSD) { std::string command = "AT+CUSD=1"; std::vector response; SendCommand(command); ReadCommandResponse(response); ASSERT_EQ(response.size(), 1); ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, testCLIR) { std::string command = "AT+CLIR=2"; std::vector response; SendCommand(command); ReadCommandResponse(response); ASSERT_EQ(response.size(), 1); ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, testQueryCLIR) { std::string command = "AT+CLIR?"; std::vector response; SendCommand(command, "+CLIR:"); ReadCommandResponse(response); ASSERT_EQ(response.size(), 2); } TEST_F(ModemServiceTest, testCallWaiting) { std::string command = "AT+CCWA"; std::vector response; SendCommand(command, "+CCWA:"); ReadCommandResponse(response); ASSERT_EQ(response.size(), 1); ASSERT_STREQ(response[response.size() - 1].c_str(), kFinalResponseSuccess[0].c_str()); } TEST_F(ModemServiceTest, testCLIP) { std::string command = "AT+CLIP?"; std::vector response; SendCommand(command, "+CLIP:"); ReadCommandResponse(response); ASSERT_EQ(response.size(), 2); } TEST_F(ModemServiceTest, testCallForward) { std::string command = "AT+CCFCU=1,1,2,145,\"10086\""; std::vector response; SendCommand(command, "+CCFCU:"); ReadCommandResponse(response); ASSERT_EQ(response.size(), 1); } /* STK Service Test */ TEST_F(ModemServiceTest, ReportStkServiceIsRunning) { std::string command = "AT+CUSATD?"; std::vector response; SendCommand(command); ReadCommandResponse(response); ASSERT_EQ(response.size(), 2); const char *result = response[0].c_str(); const char *expect = "+CUSATD: 0,1"; ASSERT_STREQ(result, expect); } TEST_F(ModemServiceTest, SendEnvelope) { std::string command = "AT+CUSATT=\"810301250002028281830100\""; std::vector response; SendCommand(command); ReadCommandResponse(response); ASSERT_EQ(response.size(), 2); const char *result = response[0].c_str(); const char *expect = "+CUSATT: 0"; ASSERT_STREQ(result, expect); } TEST_F(ModemServiceTest, GetSendTerminalResponseToSim) { std::string command = "AT+CUSATE=\"D3078202018190014E\""; std::vector response; SendCommand(command); ReadCommandResponse(response); ASSERT_EQ(response.size(), 2); const char *result = response[0].c_str(); const char *expect = "+CUSATE: 0"; ASSERT_STREQ(result, expect); } /* Misc Service Test */ TEST_F(ModemServiceTest, GetIMEI) { std::string command = "AT+CGSN"; std::vector response; SendCommand(command); ReadCommandResponse(response); ASSERT_EQ(response.size(), 2); const char *result = response[0].c_str(); const char *expect = "867400022047199"; ASSERT_STREQ(result, expect); }