- CitrineOS core extracted (CSMS OCPP 2.0.1) - OpenOCPP extracted (firmware OCPP 1.6J/2.0.1) - ShapeShifter library installed (pip install -e) - ShapeShifter specification extracted - EVerest extracted TODO updated with progress
164 lines
6.0 KiB
C++
164 lines
6.0 KiB
C++
// SPDX-License-Identifier: Apache-2.0
|
|
// Copyright chargebyte GmbH and Contributors to EVerest
|
|
|
|
#include <everest/logging.hpp>
|
|
#include <gtest/gtest.h>
|
|
#include <thread>
|
|
|
|
#include "../helpers/WebSocketTestClient.hpp"
|
|
#include "../server/WebsocketServer.hpp"
|
|
|
|
using namespace server;
|
|
|
|
class WebSocketServerTest : public ::testing::Test {
|
|
protected:
|
|
std::unique_ptr<WebSocketServer> ws_server;
|
|
int test_port = 8080;
|
|
|
|
void SetUp() override {
|
|
ws_server = std::make_unique<WebSocketServer>(false, test_port, "lo");
|
|
lws_set_log_level(LLL_ERR | LLL_WARN, NULL);
|
|
|
|
ws_server->on_client_connected = [this](const TransportInterface::ClientId& client_id,
|
|
const server::TransportInterface::Address& address) {
|
|
// Handle client connected logic here
|
|
std::lock_guard<std::mutex> lock(cv_mutex);
|
|
try {
|
|
connected_clients.push_back(client_id);
|
|
} catch (const std::exception& e) {
|
|
EVLOG_error << "Exception occurred while handling client connected: " << e.what();
|
|
}
|
|
};
|
|
|
|
ws_server->on_client_disconnected = [this](const TransportInterface::ClientId& client_id) {
|
|
// Handle client disconnected logic here
|
|
std::lock_guard<std::mutex> lock(cv_mutex);
|
|
try {
|
|
connected_clients.erase(std::remove(connected_clients.begin(), connected_clients.end(), client_id),
|
|
connected_clients.end());
|
|
} catch (const std::exception& e) {
|
|
EVLOG_error << "Exception occurred while handling client disconnected: " << e.what();
|
|
}
|
|
};
|
|
|
|
ws_server->on_data_available = [this](const TransportInterface::ClientId& client_id,
|
|
const server::TransportInterface::Data& data) {
|
|
// Handle data available logic here
|
|
std::lock_guard<std::mutex> lock(cv_mutex);
|
|
try {
|
|
received_data[client_id] = std::string(data.begin(), data.end());
|
|
cv.notify_all();
|
|
} catch (const std::exception& e) {
|
|
EVLOG_error << "Exception occurred while handling data available: " << e.what();
|
|
}
|
|
};
|
|
|
|
ws_server->start_server();
|
|
}
|
|
|
|
std::vector<TransportInterface::ClientId>& get_connected_clients() {
|
|
std::lock_guard<std::mutex> lock(cv_mutex);
|
|
return connected_clients;
|
|
}
|
|
|
|
// Connected client id's
|
|
std::vector<TransportInterface::ClientId> connected_clients;
|
|
|
|
// Condition variable to wait requests
|
|
std::condition_variable cv;
|
|
std::mutex cv_mutex;
|
|
|
|
// Received data with client id
|
|
std::unordered_map<TransportInterface::ClientId, std::string> received_data;
|
|
|
|
void TearDown() override {
|
|
ws_server->stop_server();
|
|
}
|
|
};
|
|
|
|
// Test: Start and stop WebSocket server
|
|
TEST_F(WebSocketServerTest, WebSocketServerStarts) {
|
|
ASSERT_TRUE(ws_server->running());
|
|
TearDown();
|
|
ASSERT_FALSE(ws_server->running());
|
|
}
|
|
|
|
// Test: Connect WebSocket client to server
|
|
TEST_F(WebSocketServerTest, ClientCanConnect) {
|
|
WebSocketTestClient client("localhost", test_port);
|
|
ASSERT_TRUE(client.connect());
|
|
ASSERT_TRUE(client.wait_until_connected(std::chrono::milliseconds(100)));
|
|
}
|
|
|
|
// Test: Connect several WebSocket clients to server
|
|
TEST_F(WebSocketServerTest, MultipleClientsCanConnect) {
|
|
WebSocketTestClient client1("localhost", test_port);
|
|
WebSocketTestClient client2("localhost", test_port);
|
|
WebSocketTestClient client3("localhost", test_port);
|
|
|
|
ASSERT_TRUE(client1.connect());
|
|
ASSERT_TRUE(client2.connect());
|
|
ASSERT_TRUE(client3.connect());
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
|
|
ASSERT_TRUE(client1.is_connected());
|
|
ASSERT_TRUE(client2.is_connected());
|
|
ASSERT_TRUE(client3.is_connected());
|
|
|
|
ASSERT_TRUE(ws_server->connections_count() == 3);
|
|
}
|
|
|
|
// Test: Client can send data to server
|
|
TEST_F(WebSocketServerTest, ClientCanSendAndReceiveData) {
|
|
WebSocketTestClient client("localhost", test_port);
|
|
ASSERT_TRUE(client.connect());
|
|
ASSERT_TRUE(client.wait_until_connected(std::chrono::milliseconds(100)));
|
|
|
|
client.send("Hello World!");
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
|
|
std::unique_lock<std::mutex> lock(cv_mutex);
|
|
cv.wait_for(lock, std::chrono::seconds(1), [&] { return !received_data.empty(); });
|
|
lock.unlock();
|
|
|
|
ASSERT_EQ(ws_server->connections_count(), 1);
|
|
ASSERT_EQ(received_data[(get_connected_clients()[0])], "Hello World!");
|
|
}
|
|
|
|
// Test: Server can send data to client
|
|
TEST_F(WebSocketServerTest, ServerCanSendDataToClient) {
|
|
WebSocketTestClient client("localhost", test_port);
|
|
ASSERT_TRUE(client.connect());
|
|
ASSERT_TRUE(client.wait_until_connected(std::chrono::milliseconds(100)));
|
|
|
|
std::string message = "Hello from server!";
|
|
ws_server->send_data(get_connected_clients()[0], std::vector<uint8_t>(message.begin(), message.end()));
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
std::string received_data = client.wait_for_data(std::chrono::seconds(1), false);
|
|
|
|
ASSERT_FALSE(received_data.empty());
|
|
ASSERT_EQ(received_data, "Hello from server!");
|
|
}
|
|
|
|
// Test: Server kills client connection
|
|
TEST_F(WebSocketServerTest, ServerCanKillClientConnection) {
|
|
WebSocketTestClient client("localhost", test_port);
|
|
ASSERT_TRUE(client.connect());
|
|
ASSERT_TRUE(client.wait_until_connected(std::chrono::milliseconds(100)));
|
|
|
|
client.send("Hello World!");
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
|
|
client.wait_for_data(std::chrono::seconds(1));
|
|
|
|
ASSERT_EQ(ws_server->connections_count(), 1);
|
|
ASSERT_EQ(received_data[get_connected_clients()[0]], "Hello World!");
|
|
|
|
ws_server->kill_client_connection(get_connected_clients()[0], "Test kill");
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
|
|
ASSERT_EQ(ws_server->connections_count(), 0);
|
|
ASSERT_FALSE(client.is_connected());
|
|
}
|