为什么我不能为每个测试用例重新启动服务器?

时间:2018-06-04 11:04:40

标签: http c++11 server client googletest

我正在编写一些单元测试,其目的是运行websocket服务器,单元测试是连接到所述服务器的http客户端,并确保响应对应于请求。

所以我正在寻找的主要流程是:

  1. 启动服务器
  2. 运行测试X
  3. 停止服务器
  4. 基本上重复测试Y / Z / A / B

    我的代码是这样的:

    #define WEBSOCKET_SERVER_IPV4 "127.0.0.1"
    #define WEBSOCKET_SERVER_PORT "3000"
    #define WEBSOCKETSECURE_SERVER_IPV4 "127.0.0.1"
    #define WEBSOCKETSECURE_SERVER_PORT "3001"
    class WebSocketT : public ::testing ::Test{
    public:
        WebSocketT(){
            printf(">>>>>>---START WS SERVER---\n");
                cf = new ConfigManager("/opt/ra/la-d.conf");
                pid_t pid = fork();
                if (pid == 0){
                    main_websocket_process(cf);
                    exit(EXIT_SUCCESS);
                }else if (pid  > 0){
                    ws_child = pid;
                    started = 1;
                    printf("started child: %i", (int)pid);
                }
                else {
                    printf("fork failed");
                    exit(EXIT_FAILURE);
                }
    
            sleep(5);
        }
        ~WebSocketT(){
            if (started != 0){
                if (kill (ws_child, SIGKILL) != 0){
                    printf("ERROR kill: %s", strerror(errno));
                } else printf("killed");
                sleep(3);
            }
            delete cf;
        }
    private:
        pid_t ws_child;
        ConfigManager *cf;
    };
    
    
    /**
     * Test can connect normal
     */
    TEST_F(WebSocketT, connect_normal){
    // FILE* ecgwsd_fp = popen("/opt/ra/ecgwsd/bin/ecgwsd /opt/ra/ecgwsd/default.conf &", "r"); sleep(3);
        Hub h;
        bool got_open_message= false;
        h.onMessage([&got_open_message](WebSocket<CLIENT> *ws, char *message, size_t length, OpCode opCode){
            if (length == 13821){
                got_open_message = true;
                ASSERT_EQ(strncmp(message, "{\"softw", 7), 0);
            }
            if (got_open_message == true) ws->close();
            fflush(stdout);
        });
        h.onConnection([](WebSocket<uWS::CLIENT> *ws, HttpRequest req){
            //ws->send("{}");
            ws->send(ws_json_open.c_str(), ws_json_open.length(), OpCode::TEXT);
        });
        h.onDisconnection([](WebSocket<uWS::CLIENT> *ws, int code, char *message, size_t length){
            //nothign
        });
        h.onError([](void * u){
            printf("ERROR in websocket connection");
            FAIL();
    
        });
        h.connect("ws://" WEBSOCKET_SERVER_IPV4 ":" WEBSOCKET_SERVER_PORT "/TESTSTS", nullptr );
        h.run();
    };
    
    
    /**
     * Test can connect secure
     */
    TEST_F(WebSocketT, connect_secure){
        Hub h;
        bool ssl_connected = false;
        h.onMessage([](WebSocket<SERVER> *ws, char *message, size_t length, OpCode opCode){
            printf("Was a message");
        });
        h.onConnection([&ssl_connected](WebSocket<uWS::CLIENT> *ws, HttpRequest req){
                //ws->send("{}");
            ssl_connected = true;
            ws->close();
        });
        h.onDisconnection([&ssl_connected](WebSocket<uWS::CLIENT> *ws, int code, char *message, size_t length){
            ASSERT_EQ(ssl_connected, true);
        });
        h.onError([](void * u){
                printf("ERROR in websocket secure connection, %s", (char*) u);
                FAIL();
        });
        h.connect("wss://" WEBSOCKETSECURE_SERVER_IPV4 ":" WEBSOCKETSECURE_SERVER_PORT "/", nullptr );
        h.run();
    };
    

    所以这里我们的测试X是:正常/安全

    问题是,当我运行它时,connect_normal可以连接到服务器,但connect_secure不能。如果我注释掉connect_normal,那么连接安全就可以了。

    我还尝试通过将websocket服务器编译为单独的二进制文件而不是将其作为“/ path / to / binary / websocket_server --port = 3242&amp;”运行来解决此问题。在gitlab的连续集成配置中。这有完全相同的问题。

    我能解决这个问题的唯一方法是创建一个单独的二进制文件,它可以作为一个独立的可执行文件运行,而不是在每个测试用例的开头我用popen ("/path/to/websocket/server --port=3434 &", "r"); sleep(3);运行可执行文件,睡眠是允许服务器有一段时间启动。这个单独的二进制文件也运行“main_websocket_process”,但是在主函数内(+日志+信号处理) - 所以逻辑上它应该在websocket活动方面做同样的事情。

    使用popen和sleep看起来很脏,那么有没有办法为每个测试用例干净地运行这个服务器?为服务器编写模拟是不实际的。另外,为什么上面的代码适用于单个测试用例,但是下一个代码失败?它应该在每个测试用例上运行构造函数和析构函数吗?

0 个答案:

没有答案
相关问题