diff --git a/CMakeLists.txt b/CMakeLists.txt index 719a92e..d04a180 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -200,6 +200,7 @@ if(PRAAS_WITH_TESTING) set(TESTS #tests/integration/invocation.cpp tests/integration/allocation_invocation.cpp + tests/integration/state_swap.cpp ) foreach(test ${TESTS}) diff --git a/examples/state-cpp/CMakeLists.txt b/examples/state-cpp/CMakeLists.txt new file mode 100644 index 0000000..34e2ebb --- /dev/null +++ b/examples/state-cpp/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.11) +project(praas-benchmarks) + +find_package(runtime) + +add_library(state SHARED state.cpp) +target_link_libraries(state PRIVATE praas::runtime) +target_link_libraries(state PRIVATE praas::cereal) +set_target_properties(state PROPERTIES LIBRARY_OUTPUT_DIRECTORY functions) +set(FUNCTIONS_DIRECTORY ${CMAKE_BINARY_DIR}) +configure_file(functions.json.in functions/functions.json @ONLY) diff --git a/examples/state-cpp/functions.json.in b/examples/state-cpp/functions.json.in new file mode 100644 index 0000000..d05dcf2 --- /dev/null +++ b/examples/state-cpp/functions.json.in @@ -0,0 +1,26 @@ +{ + "functions": { + "cpp": { + "state-put": { + "code": { + "module": "@FUNCTIONS_DIRECTORY@/libstate.so", + "function": "state_put" + }, + "trigger": { + "type": "direct", + "nargs": 1 + } + }, + "state-get": { + "code": { + "module": "@FUNCTIONS_DIRECTORY@/libstate.so", + "function": "state_get" + }, + "trigger": { + "type": "direct", + "nargs": 1 + } + } + } + } +} diff --git a/examples/state-cpp/state.cpp b/examples/state-cpp/state.cpp new file mode 100644 index 0000000..dea568f --- /dev/null +++ b/examples/state-cpp/state.cpp @@ -0,0 +1,72 @@ + +#include +#include + +#include +#include + +#include +#include +#include +#include + +struct IO { + std::string message; + + template + void save(Ar & archive) const + { + archive(CEREAL_NVP(message)); + } + + template + void load(Ar & archive) + { + archive(CEREAL_NVP(message)); + } +}; + +extern "C" int state_put( + praas::process::runtime::Invocation invocation, praas::process::runtime::Context& context +) +{ + IO msg; + invocation.args[0].deserialize(msg); + + praas::process::runtime::Buffer buf = context.state("STATE_MSG_1"); + + auto send_buf = context.get_buffer(1024); + send_buf.serialize(msg); + + context.state("STATE_MSG_1", send_buf); + + msg.message = "second_state_msg"; + send_buf.serialize(msg); + context.state("STATE_MSG_2", send_buf); + + msg.message = "42424242"; + send_buf.serialize(msg); + context.state("STATE_MSG_3", send_buf); + + std::filesystem::create_directories("/state/test1/test2/"); + std::ofstream out{"/state/test1/test2/TEST"}; + out << "newfiledata"; + out.close(); + + return 0; +} + +extern "C" int state_get( + praas::process::runtime::Invocation invocation, praas::process::runtime::Context& context +) +{ + IO key; + praas::process::runtime::Buffer buf = context.state("STATE_MSG_1"); + buf.deserialize(key); + + auto& output_buf = context.get_output_buffer(1024); + output_buf.serialize(key); + context.set_output_buffer(output_buf); + + return 0; +} diff --git a/tests/integration/state_swap.cpp b/tests/integration/state_swap.cpp new file mode 100644 index 0000000..94d6d7f --- /dev/null +++ b/tests/integration/state_swap.cpp @@ -0,0 +1,93 @@ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +struct Result { + std::string msg; + + template + void save(Ar& archive) const + { + archive(CEREAL_NVP(msg)); + } + + template + void load(Ar& archive) + { + archive(CEREAL_NVP(msg)); + } +}; + +class IntegrationLocalInvocation : public ::testing::Test {}; + +std::string get_output_binary(const char* buffer, size_t size) +{ + Result out; + boost::iostreams::stream stream(buffer, size); + cereal::BinaryInputArchive archive_in{stream}; + out.load(archive_in); + + return out.msg; +} + +std::string get_input_binary(Result& msg) +{ + std::string result; + result.resize(1024); + + boost::interprocess::bufferstream out_stream(reinterpret_cast(result.data()), 1024); + cereal::BinaryOutputArchive archive_out{out_stream}; + archive_out(msg); + + return result; +} + +TEST_F(IntegrationLocalInvocation, AllocationInvoke) +{ + praas::common::http::HTTPClientFactory::initialize(1); + { + praas::sdk::PraaS praas{fmt::format("http://127.0.0.1:{}", 9000)}; + + std::string app_name("test_alloc_invoc"); + ASSERT_TRUE( + praas.create_application(app_name, "spcleth/praas:proc-local") //spcleth/praas-examples:hello-world-cpp") + ); + + auto proc = praas.create_process(app_name, "alloc_invoc_process", "1", "1024"); + ASSERT_TRUE(proc.has_value()); + spdlog::info("Created process"); + + ASSERT_TRUE(proc->connect()); + + Result msg; + msg.msg = "TEST_SWAP"; + auto res = get_input_binary(msg); + + auto invoc = proc->invoke("state-put", "invocation-id", res.data(), res.size()); + spdlog::info("Invoked"); + + // auto invoc = praas.invoke("test_app", "hello-world", ""); + + ASSERT_EQ(invoc.return_code, 0); + + auto swap_res = praas.swap_process(proc.value()); + ASSERT_TRUE(swap_res.has_value()); + spdlog::info(swap_res.value()); + + ASSERT_TRUE(praas.delete_process(proc.value())); + + ASSERT_TRUE(praas.delete_application(app_name)); + } +}