1、测试用例的逻辑

  • 测试用例一旦运行,则调用预置执行函数 preDeal(FunctionHandler handler),该函数获取测试用例的进程 ID,并记录在 jsonObject(jsonObject["process_id"] = processId;);

  • 预置执行函数设置回调函数 signalHandler,测试用例一旦收到 SIGUSR1 或 SIGINT 信号,则执行回调函数。回调函数第一步就是从[测试用例实例]的消息队列里获取 cmd 命令。[测试用例实例]根据测试用例的进程 ID 获取消息队列 msgget(m_process_id, IPC_CREAT | 0666),并从消息队列里获取 cmd 数据;

  • 根据 cmd 的值执行不同的操作。如在 test_lear_ota.cpp 中,若 cmd==clear_ota,则调用系统调用函数 system(shellCmd.c_str()),其中 std::string shellCmd = "/fctdata/dv/update.sh";。并通过[测试用例实例]的日志记录执行信息。操作执行后,记录测试用例的执行结果 jsonObject["result"] = "xxx"

  • 测试用例与 epoller 通过管道通信的原理: epoller 通过 popen() 启动测试用例,测试用例 getpid() 获取 procssId,并通过管道回写给 epoller,这样双方都可以根据 processId 来通过消息队列进行通信。之所以已经有管道,还使用消息队列进行通信,原因是:相比管道,消息队列可以通过发送消息来避免命名管道的同步和阻塞问题。

2、测试用例通用的 preDeal() 的理解

创建或获取以进程 ID 为标识符的消息队列。

std::shared_ptr<MsgQueue> g_msgQueuePtr = nullptr;

void signalHandler()
{
    // 测试用例通过消息队列获取 SOC 传过来的 cmd
    std::string cmd = g_msgQueuePtr->receiveMessage();
    
    ``` msg_queue.cpp:
      // 测试用例的消息队列 id 与自身的进程号相同
      m_msg_queue_id = msgget(m_process_id, IPC_CREAT | 0666); 

    ```

    ```message.cpp 
       // 收到 pc 的消息(对应下处下位机日志),将测试用例相关信息用结构体记录下来
       MessageSendMsg::responce()
       {
         for (const auto &it : jsonMessage)
         {
          std::string errorMessage;
          auto testItemPtr = TestItemConfig::json2TestItem(it, errorMessage);
         }
       }
    ```

    ```下位机日志 
   2024-03-01 11:23:18.979 [info] 收到通道(pc)的消息:{"message": [{"bin":"test_soc_soft_ver","chip":"SOC1","key":11,"msg":"rtc","name":"start_soc_soft_ver","parameter":"","test":true,"type":"parallel_test"}],"message_type":"send_message"}
   2024-03-01 11:23:18.979 [info] 给测试用例start_soc_soft_ver发消息成功:rtc
    ```

}

int main(int argc, char **argv)
{
    g_msgQueuePtr = TestItemPreprocess::instance().preDeal(signalHandler);
    ...
}

3、对 msg 的理解

  • PC 会发送多个 msg 给同一个测试用例
[line 22]收到通道(pc)的消息:{"message":[{"bin":"test_soc_soft_ver","chip":"SOC1","key":11,"msg":"rtc","name":"start_soc_soft_ver","parameter":""
[line48]给pc发送报文:{"message":{"bin":"test_soc_soft_ver","chip":"SOC1","key":11,"name":"start_soc_soft_ver","parameter":"eol","result":"{\"name\":\"rtc\",\"value\":[\"MPQ79700FS's RTC Read Test starts:\",\">> RTC time in seconds since the epoch (1970/01/01 UTC): 1709292199\",\">> Convert RTC time to Universal time: Fri Mar  1 11:23:19 UTC 2024\"]}","test":true,"type":"parallel_test"},"message_type":"test_item_result"}
[line 189]收到通道(pc)的消息:{"message":[{"bin":"test_soc_soft_ver","chip":"SOC1","key":11,"msg":"soc_ver","name":"start_soc_soft_ver","parameter":""
[line 240]收到通道(pc)的消息:{"message":[{"bin":"test_soc_soft_ver","chip":"SOC1","key":11,"msg":"switch_ver","name":"test_soc_soft_ver"
...

2、测试用例创建子进程的方式

2.1、system()

ret = system(shellCmd.c_str());

2.2、std::thread

std::vector<std::thread> threads;
for (int i = 0; i < 1; i++)
{
    //std::string shellCmd = "nice -n 19 taskset -c " + std::to_string(i) + " systester -gausslg 32M -bench  > /dev/null";
    std::string shellCmd = "nice -n 19 stress-ng -c " + std::to_string(num) + " --taskset 3-" + std::to_string(3+num-1);
    threads.emplace_back([](const std::string shellCmd)
                            {
                                //std::cout << std::this_thread::get_id() << std::endl;
                                UtilShell::getShellNoResult(shellCmd);
                            },
                            shellCmd);
}
for (auto &it : threads)
{
    it.join();
}

3、对日志的理解

  • 测试用例每执行一条 shellCmd,必定要用 log 记录,记录格式为:
jsonObject["log_level"] = "error"/"info";
jsonObject["log"] = msg;

工作内容:1)双 SOC 均部署 Epoll Server,SOC1 通过 TCP 与 SOC2 及上位机进行通信,通过 popen 启动测试用例并通过消息队列及信号进行通信,通过 SOMEIP 与 MCU 建立通信;2)SOC1 通过缓冲队列转发或执行测试用例集合,并将执行结果写入日志文件,并封装成响应报文返回给上位机。

补充:负责排查及定位产测模块版本迭代出现的联调问题。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。