Skip to content

Commit

Permalink
On exit wait due issues in GA testing
Browse files Browse the repository at this point in the history
Add extra event on open

Add extra event on open

Remove ui_ready from uWs server is_connected as that caused blocking Apitests

Version bump
  • Loading branch information
mmertama committed Mar 24, 2024
1 parent 653dfc7 commit 0d43dc4
Show file tree
Hide file tree
Showing 15 changed files with 86 additions and 31 deletions.
2 changes: 1 addition & 1 deletion gempyrelib/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#cmake_minimum_required (VERSION 3.18)


project (gempyre VERSION 1.3.4 LANGUAGES CXX C)
project (gempyre VERSION 1.3.5 LANGUAGES CXX C)
# Must use GNUInstallDirs to install libraries into correct
# locations on all platforms.
include(GNUInstallDirs)
Expand Down
3 changes: 3 additions & 0 deletions gempyrelib/include/gempyre.h
Original file line number Diff line number Diff line change
Expand Up @@ -457,11 +457,14 @@ namespace Gempyre {
/// test if Element can be accessed. Note that in false it's may be in HTML, but not available in DOM tree.
bool available(const std::string& id) const;


/// @cond INTERNAL
// for testing
void resume();
// for testing
void suspend();
// for testing
bool ui_available() const;
/// @endcond

private:
Expand Down
7 changes: 7 additions & 0 deletions gempyrelib/js/gempyre.js
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,13 @@ socket.onopen = function(event) {
if(socket.readyState === 1)
socket.send(JSON.stringify({'type': 'keepalive'}));
}, 10000); //decreased to help more intensive cal app messages (read mandelbrot) get passed

// one guess is that in API tests there no events coming
setTimeout(function() {
socket.send(JSON.stringify({'type': 'event',
'element': '', 'event': 'ui_ready', 'properties':{}}));
}, 100);

socket.send(JSON.stringify({'type': 'ui_ready'}));
};

Expand Down
6 changes: 5 additions & 1 deletion gempyrelib/src/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ void Ui::set_timer_on_hold(bool on_hold) {
}

bool Ui::is_timer_on_hold() const {
return m_ui->hold();
return m_ui->is_hold();
}


Expand Down Expand Up @@ -519,3 +519,7 @@ void Ui::flush() {
m_ui->shoot_requests();
}

bool Ui::ui_available() const {
return m_ui->is_connected() && m_ui->is_running();
}

10 changes: 10 additions & 0 deletions gempyrelib/src/gempyre_internal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ void GempyreInternal::openHandler() {
set(State::RELOAD);
}
signal_pending(); // there may be some pending requests
shoot_requests();
}

void GempyreInternal::closeHandler(Gempyre::CloseStatus closeStatus, int code) { //close
Expand Down Expand Up @@ -488,6 +489,7 @@ void GempyreInternal::eventLoop(bool is_main) {
}

if(has_open() && *this == State::RUNNING && is_connected()) {
GempyreUtils::log(GempyreUtils::LogLevel::Debug, "has open running", state_str());
const auto fptr = take_open();
set_hold(true);
add_request([fptr, this]() {
Expand Down Expand Up @@ -581,6 +583,14 @@ std::function<void(int)> GempyreInternal::makeCaller(const std::function<void (U
void GempyreInternal::consume_events() {
while(has_events() && *this == State::RUNNING) {
const auto it = m_eventqueue.take();
if(it.element.empty()) {
GempyreUtils::log(GempyreUtils::LogLevel::Debug,
"Root got event:", it.handler,
"has open:", has_open(),
"State:", state_str(),
"Connected", is_connected());
continue;
}
const auto element = m_elements.find(it.element);
if(element != m_elements.end()) {
const auto handlerName = it.handler;
Expand Down
13 changes: 7 additions & 6 deletions gempyrelib/src/gempyre_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ class GempyreInternal {


void signal_pending() {
m_sema.signal(); // there may be some pending requests
m_sema.signal(); // there may be some pending requests
}

void push_event(HandlerEvent&& event) {
Expand Down Expand Up @@ -292,7 +292,7 @@ class GempyreInternal {
m_hold = on_hold;
}

bool hold() const {
bool is_hold() const {
return m_hold;
}

Expand Down Expand Up @@ -404,9 +404,10 @@ class GempyreInternal {
}

std::function<void()> take_open() {
const auto fptr = std::move(m_onOpen);
m_onOpen = nullptr;
return fptr;
GEM_DEBUG("Take open");
const auto fptr = std::move(m_onOpen);
m_onOpen = nullptr;
return fptr;
}

void do_exit() {
Expand Down Expand Up @@ -467,7 +468,7 @@ class GempyreInternal {

void wait_events() {
const auto start = std::chrono::steady_clock::now();
if(*this == State::CLOSE || *this == State::EXIT)
if(*this == State::CLOSE || *this == State::EXIT || !m_server || !m_server->isRunning())
m_sema.wait(300ms);
else
m_sema.wait();
Expand Down
2 changes: 2 additions & 0 deletions gempyrelib/src/libwebsockets/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,10 +340,12 @@ bool LWS_Server::isRunning() const {
assert(isJoinable());
return m_running;
}

bool LWS_Server::isConnected() const {
assert(isRunning());
return m_connected;
}

bool LWS_Server::retryStart() {std::abort();}

void LWS_Server::close(bool wait) {
Expand Down
1 change: 1 addition & 0 deletions gempyrelib/src/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -968,6 +968,7 @@ int GempyreUtils::execute(const std::string& executable, const std::string& para
return static_cast<int>((hi > 32 || hi < 0) ? 0 : hi); //If the function succeeds, it returns a value greater than 32. If the function fails, it returns an error value that indicates the cause of the failure.
}
#else
std::cout << std::endl; // flush
return std::system((executable + " " + parameters + " &").c_str());
#endif
}
Expand Down
3 changes: 2 additions & 1 deletion gempyrelib/src/uwebsockets/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class Gempyre::SocketHandler {
GempyreUtils::log(GempyreUtils::LogLevel::Debug, "WS open");
m_s.m_broadcaster->append(ws);
m_s.m_onOpen();
GempyreUtils::log(GempyreUtils::LogLevel::Debug, "WS opened");
}


Expand Down Expand Up @@ -357,7 +358,7 @@ bool Uws_Server::retryStart() {
}

bool Uws_Server::isConnected() const {
return !m_broadcaster->empty() && m_uiready;
return !m_broadcaster->empty() /*&& m_uiready*/; // why was this -
}

bool Uws_Server::beginBatch() {
Expand Down
12 changes: 7 additions & 5 deletions test/apitests/gempyre_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ void GempyreTest::killHeadless() {
? R"(powershell.exe -command "Get-CimInstance -ClassName Win32_Process -Filter \"CommandLine LIKE '%--headless%'\" | %{Stop-Process -Id $_.ProcessId}")"
: "pkill -f \"(chrome)?(--headless)\"";
const auto killStatus = std::system(cmd);
(void) killStatus;
GempyreUtils::log(GempyreUtils::LogLevel::Info, "killHeadles", killStatus);
}


Expand Down Expand Up @@ -131,12 +131,12 @@ void TestUi::SetUp() {
std::exit(1);
});
const auto wait_start = GempyreUtils::wait_expire(30s, []() {
GempyreUtils::log(GempyreUtils::LogLevel::Error, "Chrome not start");
FAIL() << "Chrome not start!";
GempyreUtils::log(GempyreUtils::LogLevel::Error, "Chrome not started");
FAIL() << "Chrome not started!" << " ui:" << (m_ui->ui_available() ? "ok" : "nok") << " t:" << (m_ui->is_timer_on_hold() ? "ok" : "nok");
std::exit(2);
});
m_ui->on_open([wait_start](){
GEM_DEBUG("test ui on");
PRINT_D("test ui on");
});
#ifdef FAST
m_ui->after(0ms, []() {
Expand Down Expand Up @@ -247,5 +247,7 @@ int main(int argc, char **argv) {
if(argv[i] == std::string_view("--verbose"))
Gempyre::set_debug();
killHeadless(); // there may be unwanted processes
return RUN_ALL_TESTS();
const auto exit_code = RUN_ALL_TESTS();
killHeadless();
return exit_code;
}
3 changes: 3 additions & 0 deletions test/apitests/gempyre_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@
#include <functional>
#include <chrono>
#include <string_view>
#include <iostream>

using namespace std::chrono_literals;

#define PRINT_D(_X) std::cout << "\033[0;32m" << "[ ] " << "\033[0;0m" << _X << std::endl;

namespace GempyreTest {
void killHeadless();
class TestUi : public testing::Test {
Expand Down
22 changes: 15 additions & 7 deletions test/apitests/mock_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#endif
#include "apitests_resource.h"
#include <cassert>
#include <iostream>

#include <gtest/gtest.h>

Expand All @@ -19,12 +20,14 @@
#ifdef RASPBERRY_OS
constexpr auto WaitExpireTimeout = 30s;
#else
constexpr auto WaitExpireTimeout = 10s;
constexpr auto WaitExpireTimeout = 20s;
#endif

#define PRINT_D(_X) std::cout << "\033[0;35m" << "[ ] " << "\033[0;0m" << _X << std::endl;


//#define HANDLE_EXPIRE ui.exit()
#define HANDLE_EXPIRE std::abort()
#define HANDLE_EXPIRE GempyreUtils::log(GempyreUtils::LogLevel::Error, "Annoying!"); ADD_FAILURE() << "Chrome not start! o:" << (ok ? "opn": "nopn")<< " ui:" << (ui.ui_available() ? "ok" : "nok") << " t:" << (ui.is_timer_on_hold() ? "hold" : "nold"); std::abort();

TEST(TestMockUi, openPage_with_page_browser) {
constexpr auto htmlPage = TEST_HTML;
Expand All @@ -42,14 +45,14 @@ TEST(TestMockUi, openPage_with_page_browser) {
Gempyre::Ui ui(map, *url, TEST_BINARY, "");
bool ok = false;
ui.on_open([&ui, &ok]() {
PRINT_D("Test open 1");
ok = true;
ui.exit();
});
ui.on_error([](const auto& element, const auto& info) {
FAIL() << element << " err:" << info;
});
const auto raii_ex = GempyreUtils::wait_expire(WaitExpireTimeout, [&]() {
FAIL() << "Expired!";
HANDLE_EXPIRE;
});
ui.run();
Expand All @@ -72,6 +75,7 @@ TEST(TestMockUi, openPage_with_page) {
Gempyre::Ui ui(map, *url, TEST_BINARY, "");
bool ok = false;
ui.on_open([&ui, &ok]() {
PRINT_D("Test open 2");
ok = true;
ui.exit();
});
Expand All @@ -91,6 +95,7 @@ TEST(TestMockUi, openPage_with_browser) {
Gempyre::Ui ui({{"/foobar.html", Apitestshtml}}, "foobar.html", TEST_BINARY, "");
bool ok = false;
ui.on_open([&ui, &ok]() {
PRINT_D("Test open 3");
ok = true;
ui.exit();
});
Expand All @@ -110,13 +115,13 @@ TEST(TestMockUi, openPage_defaults) {
TEST_UI;
bool ok = false;
ui.on_open([&ui, &ok]() {
PRINT_D("Test open 4");
ASSERT_FALSE(ok);
ok = true;
ui.exit();
});
ui.on_error([](const auto& element, const auto& info){FAIL() << element << " err:" << info;});
const auto raii_ex = GempyreUtils::wait_expire(WaitExpireTimeout, [&]() {
FAIL() << "Expired!";
HANDLE_EXPIRE;
});
ui.run();
Expand All @@ -131,11 +136,11 @@ TEST(TestMockUi, onExit) {
ui.exit();
});
ui.on_exit([&ok]() {
PRINT_D("Test open 5");
ASSERT_FALSE(ok);
ok = true;
});
const auto raii_ex = GempyreUtils::wait_expire(WaitExpireTimeout, [&]() {
FAIL() << "Expired!";
HANDLE_EXPIRE;
});
ui.run();
Expand Down Expand Up @@ -164,11 +169,14 @@ TEST(TestMockUi, alert) {
TEST_UI;
bool ok = false;
ui.on_open([&ui, &ok]() {
PRINT_D("Test open 6");
ui.alert("Test - Alert");
ok = true;
ui.exit();
});
const auto raii_ex = GempyreUtils::wait_expire(WaitExpireTimeout, []() { FAIL() << "Expired!";});
const auto raii_ex = GempyreUtils::wait_expire(WaitExpireTimeout, [&]() {
HANDLE_EXPIRE;
});
ui.run();
ASSERT_TRUE(ok);
}
Expand All @@ -180,12 +188,12 @@ TEST(TestMockUi, open) {
TEST_UI;
bool ok = false;
ui.on_open([&ui, &ok]() {
PRINT_D("Test open 7");
ui.open("http://www.google.com");
ok = true;
ui.exit();
});
const auto raii_ex = GempyreUtils::wait_expire(WaitExpireTimeout, [&]() {
FAIL() << "Expired!";
HANDLE_EXPIRE;
});
ui.run();
Expand Down
2 changes: 1 addition & 1 deletion test/mock_browser/ws.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ callback(lws* wsi, lws_callback_reasons reason, void* user, void* in, size_t len
lwsl_user("%s: established connection, wsi = %p\n",
__func__, wsi);
mco->m_connections->emplace(wsi);
send_message(mco, mco->extension->on_status(websocket::Status::Established));
mco->extension->on_status(websocket::Status::Established);
break;

case LWS_CALLBACK_CLIENT_CLOSED:
Expand Down
2 changes: 1 addition & 1 deletion test/mock_browser/ws.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace websocket {
class App {
public:
int received(const char* cstr);
std::string on_status(Status status);
bool on_status(Status status);
std::function<void ()> exit = nullptr;
std::function<bool (const char* cstr)> send_message = nullptr;
};
Expand Down
29 changes: 21 additions & 8 deletions test/mock_browser/ws_app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,41 @@
#include "ws.hpp"
#include <iostream>
#include <chrono>
#include <thread>

using namespace std::chrono_literals;

#include <nlohmann/json.hpp>
using namespace websocket;
using Json = nlohmann::json;

std::string App::on_status(websocket::Status status) {
bool App::on_status(websocket::Status status) {
switch(status) {
case websocket::Status::Error:
return Json({{"type", "error"}}).dump();
case websocket::Status::Established:
return Json({{"type", "ui_ready"}}).dump();
case websocket::Status::Error: {
const auto err = Json({{"type", "error"}}).dump();
send_message(err.c_str());
return true;
}
case websocket::Status::Established: {
const auto ready = Json({{"type", "ui_ready"}}).dump();
send_message(ready.c_str());
std::this_thread::sleep_for(10ms);
const auto event = Json({{"type", "event"}, {"element", ""}, {"event", "ui_ready"}, {"properties", Json::object()}}).dump();
send_message(event.c_str());
return true;
}
// one guess is that in API tests there no events coming
default:
return false;
}
return std::string();
}

void websocket::debug_print(int lvl, const char* cstr) {
if(lvl <= WS_LOG_LEVEL)
std::cout << lvl << ":" << cstr << std::endl;
}

int App::received(const char* cstr)
{
int App::received(const char* cstr) {
const auto js = Json::parse(cstr);
if(js["type"] == "exit_request") {
exit();
Expand Down

0 comments on commit 0d43dc4

Please sign in to comment.