Skip to content

Commit

Permalink
feat: add more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
diegonehab committed Dec 5, 2024
1 parent 08d18c8 commit 8bf75ac
Show file tree
Hide file tree
Showing 11 changed files with 134 additions and 44 deletions.
6 changes: 3 additions & 3 deletions src/device-state-access.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
// with this program (see COPYING). If not, see <https://www.gnu.org/licenses/>.
//

#ifndef DEVICE_STATE_ACCESS
#define DEVICE_STATE_ACCESS
#ifndef DEVICE_STATE_ACCESS_H
#define DEVICE_STATE_ACCESS_H

/// \file
/// \brief Virtual state access implementation
Expand Down Expand Up @@ -158,4 +158,4 @@ class device_state_access : public i_device_state_access {

} // namespace cartesi

#endif
#endif // DEVICE_STATE_ACCESS_H
6 changes: 3 additions & 3 deletions src/i-device-state-access.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
// with this program (see COPYING). If not, see <https://www.gnu.org/licenses/>.
//

#ifndef I_DEVICE_STATE_ACCESS
#define I_DEVICE_STATE_ACCESS
#ifndef I_DEVICE_STATE_ACCESS_H
#define I_DEVICE_STATE_ACCESS_H

#include <cstdint>

Expand Down Expand Up @@ -231,4 +231,4 @@ class i_device_state_access {

} // namespace cartesi

#endif
#endif // I_DEVICE_STATE_ACCESS_H
6 changes: 3 additions & 3 deletions src/i-virtual-machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
// with this program (see COPYING). If not, see <https://www.gnu.org/licenses/>.
//

#ifndef I_VIRTUAL_MACHINE
#define I_VIRTUAL_MACHINE
#ifndef I_VIRTUAL_MACHINE_H
#define I_VIRTUAL_MACHINE_H

#include <cstdint>
#include <string>
Expand Down Expand Up @@ -290,4 +290,4 @@ class i_virtual_machine {

} // namespace cartesi

#endif
#endif // I_VIRTUAL_MACHINE_H
6 changes: 3 additions & 3 deletions src/jsonrpc-fork-result.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
// with this program (see COPYING). If not, see <https://www.gnu.org/licenses/>.
//

#ifndef JSONRPC_FORK_RESULT
#define JSONRPC_FORK_RESULT
#ifndef JSONRPC_FORK_RESULT_H
#define JSONRPC_FORK_RESULT_H

namespace cartesi {

Expand All @@ -26,4 +26,4 @@ struct fork_result final {

} // namespace cartesi

#endif // JSONRPC_FORK_RESULT
#endif // JSONRPC_FORK_RESULT_H
16 changes: 10 additions & 6 deletions src/jsonrpc-machine-c-api.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,6 @@ CM_API cm_error cm_jsonrpc_get_server_version(const cm_machine *m, const char **
/// This function makes it the leader of its own program group.
CM_API cm_error cm_jsonrpc_emancipate_server(cm_machine *m);

/// \brief Asks server to delay next request by a given amount of time.
/// \param m Pointer to a valid JSONRPC remote machine object.
/// \param ms Number of milliseconds to delay next request.
/// \returns 0 for success, non zero code for error.
CM_API cm_error cm_jsonrpc_delay_next_request(cm_machine *m, uint64_t ms);

// -----------------------------------------------------------------------------
// Client API functions
// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -167,6 +161,16 @@ CM_API cm_error cm_jsonrpc_get_cleanup_call(cm_machine *m, cm_jsonrpc_cleanup_ca
/// \returns 0 for success, non zero code for error.
CM_API cm_error cm_jsonrpc_get_server_address(cm_machine *m, const char **address);

// -----------------------------------------------------------------------------
// Debugging and testing
// -----------------------------------------------------------------------------

/// \brief Asks server to delay next request by a given amount of time.
/// \param m Pointer to a valid JSONRPC remote machine object.
/// \param ms Number of milliseconds to delay next request.
/// \returns 0 for success, non zero code for error.
CM_API cm_error cm_jsonrpc_delay_next_request(cm_machine *m, uint64_t ms);

#ifdef __cplusplus
}
#endif
Expand Down
26 changes: 8 additions & 18 deletions src/jsonrpc-remote-machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
#include "interpret.h"
#include "json-util.h"
#include "jsonrpc-discover.h"
#include "jsonrpc-version.h"
#include "machine-config.h"
#include "machine-merkle-tree.h"
#include "machine-runtime-config.h"
Expand Down Expand Up @@ -106,17 +107,6 @@ std::ostream &operator<<(std::ostream &out, log_prefix prefix) {
using namespace std::string_literals;
using json = nlohmann::json;

/// \brief Server semantic version major
static constexpr uint32_t server_version_major = 0;
/// \brief Server semantic version minor
static constexpr uint32_t server_version_minor = 5;
/// \brief Server semantic version patch
static constexpr uint32_t server_version_patch = 0;
/// \brief Server semantic version pre_release
static constexpr const char *server_version_pre_release = "";
/// \brief Server semantic version build
static constexpr const char *server_version_build = "";

/// \brief Installs a signal handler
template <typename HANDLER>
static void install_signal_handler(int signum, HANDLER handler) {
Expand Down Expand Up @@ -723,11 +713,11 @@ static json jsonrpc_get_version_handler(const json &j, const std::shared_ptr<htt
jsonrpc_check_no_params(j);
return jsonrpc_response_ok(j,
{
{"major", server_version_major},
{"minor", server_version_minor},
{"patch", server_version_patch},
{"pre_release", server_version_pre_release},
{"build", server_version_build},
{"major", cartesi::JSONRPC_VERSION_MAJOR},
{"minor", cartesi::JSONRPC_VERSION_MINOR},
{"patch", cartesi::JSONRPC_VERSION_PATCH},
{"pre_release", cartesi::JSONRPC_VERSION_PRE_RELEASE},
{"build", cartesi::JSONRPC_VERSION_BUILD},
});
}

Expand Down Expand Up @@ -1697,8 +1687,8 @@ int main(int argc, char *argv[]) try {

init_logger(log_level);

SLOG(info) << "remote machine server version is " << server_version_major << "." << server_version_minor << "."
<< server_version_patch;
SLOG(info) << "remote machine server version is " << cartesi::JSONRPC_VERSION_MAJOR << "."
<< cartesi::JSONRPC_VERSION_MINOR << "." << cartesi::JSONRPC_VERSION_PATCH;

install_restart_signal_handlers();

Expand Down
32 changes: 32 additions & 0 deletions src/jsonrpc-version.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option) any
// later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License along
// with this program (see COPYING). If not, see <https://www.gnu.org/licenses/>.
//

#ifndef JSONRPC_VERSION_H
#define JSONRPC_VERSION_H

#include <cstdint>

namespace cartesi {

constexpr uint32_t JSONRPC_VERSION_MAJOR = 0;
constexpr uint32_t JSONRPC_VERSION_MINOR = 5;
constexpr uint32_t JSONRPC_VERSION_PATCH = 0;
constexpr const char *JSONRPC_VERSION_PRE_RELEASE = "";
constexpr const char *JSONRPC_VERSION_BUILD = "";

} // namespace cartesi

#endif // JSONRPC_VERSION_H
16 changes: 16 additions & 0 deletions src/jsonrpc-virtual-machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "interpret.h"
#include "json-util.h"
#include "json.hpp"
#include "jsonrpc-version.h"
#include "machine-config.h"
#include "machine-memory-range-descr.h"
#include "machine-merkle-tree.h"
Expand Down Expand Up @@ -330,9 +331,23 @@ const std::string &jsonrpc_virtual_machine::get_server_address() const {
return m_address;
}

static inline std::string semver_to_string(uint32_t major, uint32_t minor) {
return std::to_string(major) + "." + std::to_string(minor);
}

void jsonrpc_virtual_machine::check_server_version() const {
const auto server_version = get_server_version();
if (server_version.major != JSONRPC_VERSION_MAJOR || server_version.minor != JSONRPC_VERSION_MINOR) {
throw std::runtime_error{"expected server version "s +
semver_to_string(JSONRPC_VERSION_MAJOR, JSONRPC_VERSION_MINOR) + " (got "s +
semver_to_string(server_version.major, server_version.minor) + ")"s};
}
}

jsonrpc_virtual_machine::jsonrpc_virtual_machine(std::string address) : m_address(std::move(address)) {
// Install handler to ignore SIGPIPE lest we crash when a server closes a connection
os_disable_sigpipe();
check_server_version();
}

static boost::asio::ip::tcp::endpoint address_to_endpoint(const std::string &address) {
Expand Down Expand Up @@ -450,6 +465,7 @@ jsonrpc_virtual_machine::jsonrpc_virtual_machine(const std::string &address, for
spawned.address = m_address;
// Install handler to ignore SIGPIPE lest we crash when a server closes a connection
os_disable_sigpipe();
check_server_version();
} catch (...) {
if (restore_sigprocmask) {
sigprocmask(SIG_SETMASK, &omask, nullptr);
Expand Down
8 changes: 5 additions & 3 deletions src/jsonrpc-virtual-machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
// with this program (see COPYING). If not, see <https://www.gnu.org/licenses/>.
//

#ifndef JSONRPC_VIRTUAL_MACHINE
#define JSONRPC_VIRTUAL_MACHINE
#ifndef JSONRPC_VIRTUAL_MACHINE_H
#define JSONRPC_VIRTUAL_MACHINE_H

#include <cstdint>
#include <memory>
Expand Down Expand Up @@ -136,6 +136,8 @@ class jsonrpc_virtual_machine final : public i_virtual_machine {
const hash_type &root_hash_before, const access_log &log, const hash_type &root_hash_after) const override;
bool do_is_jsonrpc_virtual_machine() const override;

void check_server_version() const;

mutable boost::asio::io_context m_ioc{1}; // The io_context is required for all I/O
mutable boost::beast::tcp_stream m_stream{m_ioc}; // TCP stream for keep alive connections
cleanup_call m_call{cleanup_call::nothing};
Expand All @@ -145,4 +147,4 @@ class jsonrpc_virtual_machine final : public i_virtual_machine {

} // namespace cartesi

#endif
#endif // JSONRPC_VIRTUAL_MACHINE_H
6 changes: 3 additions & 3 deletions src/virtual-machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
// with this program (see COPYING). If not, see <https://www.gnu.org/licenses/>.
//

#ifndef VIRTUAL_MACHINE
#define VIRTUAL_MACHINE
#ifndef VIRTUAL_MACHINE_H
#define VIRTUAL_MACHINE_H

#include <cstdint>
#include <string>
Expand Down Expand Up @@ -92,4 +92,4 @@ class virtual_machine : public i_virtual_machine {

} // namespace cartesi

#endif
#endif // VIRTUAL_MACHINE_H
50 changes: 48 additions & 2 deletions tests/lua/machine-test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -388,8 +388,8 @@ do_test("register values should match", function(machine)
end)

if machine_type ~= "local" then
print("\n\n check remote get_machine")
do_test("get_machine should get reference to working machine", function(machine)
print("\n\n checking remote-machine-specific functionality")
do_test("connect should get give access to working machine", function(machine)
local machine_2 = jsonrpc.connect_server(machine:get_server_address())
assert(machine:get_root_hash() == machine_2:get_root_hash())
machine_2:destroy()
Expand All @@ -400,6 +400,52 @@ if machine_type ~= "local" then
assert(err:match("no machine"))
end)

do_test("timeout mechanism should be respected", function(machine)
-- default timeout is -1 (meaning wait indefinitely)
local old_tm = machine:get_timeout()
assert(old_tm == -1)
-- set timeout to 100ms
machine:set_timeout(100)
-- make sure it stuck
assert(machine:get_timeout() == 100)
-- ask server to delay response by 1000ms
machine:delay_next_request(1000)
-- next call should fail with timeout
local ret, err = pcall(function()
machine:get_root_hash()
end)
assert(ret == false)
assert(err:match("jsonrpc error: timeout"))
machine:set_timeout(old_tm)
end)

do_test("cleanup call should be respected", function(machine)
-- all machines returned by build_machine are configured to shutdown server
assert(machine:get_cleanup_call() == jsonrpc.SHUTDOWN)
local address
do
-- fork server, get address of new server, make sure fork holds a
-- machine, and set cleanup to destroy it on close
local m2 <close> = machine:fork_server()
address = m2:get_server_address()
assert(not m2:is_empty())
m2:set_cleanup_call(jsonrpc.DESTROY)
end
do
-- connect to server again, make sure it does not have a machine
-- anymore, and set cleanup to shut it down on close
local m2 <close> = jsonrpc.connect_server(address)
assert(m2:is_empty())
m2:set_cleanup_call(jsonrpc.SHUTDOWN)
end
-- now there should be no server at that address
local ret, err = pcall(function()
jsonrpc.connect_server(address)
end)
assert(ret == false)
assert(err:match("jsonrpc error: post error contacting " .. address))
end)

do_test("jsonrpc connection error 49 after rapid successive requests ", function(machine)
-- On a Mac, this loop will break with EADDRNOTAVAIL(49)
-- Setting up the SO_LINGER to 0 fixed this issue
Expand Down

0 comments on commit 8bf75ac

Please sign in to comment.