Skip to content
Snippets Groups Projects
client_test.cc 5.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • #include <chrono>
    #include <vereign/restapi/client.hh>
    
    #include <vereign/client_library/common_types.pb.h>
    #include <vereign/client_library/identity_types.pb.h>
    #include <vereign/client_library/passport_api.gen.pb.h>
    
    #include <vereign/core/scope_guard.hh>
    #include <util/env.hh>
    
    #include "boost/asio/executor_work_guard.hpp"
    #include "catch.hpp"
    
    #include <thread>
    #include <boost/asio/io_context.hpp>
    #include <boost/asio/ssl/context.hpp>
    #include <fmt/core.h>
    #include <experiment/array.hh>
    
    TEST_CASE("Client::Post", "[vereign/restapi/client][.integration]") {
      namespace asio = boost::asio;
      namespace beast = boost::beast;
    
      asio::io_context ioc;
      auto work_guard = boost::asio::make_work_guard(ioc);
      asio::ssl::context ctx(asio::ssl::context::tlsv12_client);
    
      auto publicKey = vereign::test::RequireEnv("TEST_VEREIGN_PUB_KEY");
      auto host = vereign::test::RequireEnv("TEST_VEREIGN_API_HOST");
      auto port = vereign::test::GetEnv("TEST_VEREIGN_API_PORT", "https");
    
      // Verify the remote server's certificate
      // ctx.set_verify_mode(ssl::verify_peer);
    
      // host = "localhost";
      // port = "9292";
    
      vereign::restapi::Client client{ioc, ctx, host, port};
      std::thread ioc_thread([&ioc]{
        ioc.run();
      });
      auto on_exit = vereign::core::MakeScopeGuard(
        [&client, &ioc_thread, &work_guard] {
          client.Close();
          work_guard.reset();
          ioc_thread.join();
        }
      );
    
    
      auto req = std::make_unique<client_library::EmptyRequest>();
      auto resp = std::make_unique<client_library::LoginFormPreviousAddedDeviceResponse>();
    
    
      // const vereign::v1pb::EmptyRequest* reqptr = req.get();
      // vereign::v1pb::LoginFormPreviousAddedDeviceResponse* respptr = resp.get();
    
      auto result = client.Post(
        "/api/identity/loginWithPreviouslyAddedDevice",
        std::move(req),
        std::move(resp),
        std::vector<vereign::restapi::HttpHeader>{
          {"publicKey", publicKey}
        }
      );
    
      auto resp_ptr = result.get().Response;
      REQUIRE(resp_ptr->error() == "");
      CHECK(resp_ptr->status() == "OK");
      CHECK(resp_ptr->code() == "200");
    
      auto token = resp_ptr->data().session();
      auto uuid = resp_ptr->data().uuid();
      UNSCOPED_INFO(fmt::format("-- session: {}\n", resp_ptr->data().session()));
      UNSCOPED_INFO(fmt::format("-- uuid: {}\n", resp_ptr->data().uuid()));
    
      auto list_result = client.Post(
        "/api/passport/listPassports",
    
        std::make_unique<client_library::ListPassportsForm>(),
        std::make_unique<client_library::ListPassportsFormResponse>(),
    
        std::vector<vereign::restapi::HttpHeader>{
          {"publicKey", publicKey},
          {"token", token},
          {"uuid", uuid}
        }
      );
    
      auto list = list_result.get().Response;
      REQUIRE(list->error() == "");
      CHECK(list->status() == "OK");
      CHECK(list->code() == "200");
      CHECK(list->data().size() > 0);
      for (auto& passport : list->data()) {
        CHECK(passport.uuid().size() == 36);
      }
    }
    
    TEST_CASE("Client load test", "[vereign/restapi/client][.bench]") {
      namespace asio = boost::asio;
      namespace beast = boost::beast;
    
      asio::io_context ioc;
      auto work_guard = boost::asio::make_work_guard(ioc);
      asio::ssl::context ctx(asio::ssl::context::tlsv12_client);
    
      auto publicKey = vereign::test::RequireEnv("TEST_VEREIGN_PUB_KEY");
      auto host = vereign::test::RequireEnv("TEST_VEREIGN_API_HOST");
      auto port = vereign::test::GetEnv("TEST_VEREIGN_API_PORT", "https");
    
      host = "localhost";
      port = "9292";
    
      vereign::restapi::Client client(ioc, ctx, host, port);
      std::thread ioc_thread([&ioc]{
        ioc.run();
      });
    
      auto on_exit = vereign::core::MakeScopeGuard(
        [&client, &ioc_thread, &work_guard] {
          client.Close();
          work_guard.reset();
          ioc_thread.join();
        }
      );
    
      auto start = std::chrono::high_resolution_clock::now();
      std::vector<std::thread> threads;
      for (int i = 0; i < 10; i++) {
        auto th = i;
    
        threads.emplace_back(
          [&client, th]() mutable {
    
            auto req = std::make_unique<client_library::LoginForm>();
            auto resp = std::make_unique<client_library::LoginFormPreviousAddedDeviceResponse>();
    
    
            for (int i = 0; i < 1000; i++) {
              auto id = fmt::format("t{}-{}", th, i);
    
              req->Clear();
              resp->Clear();
              req->set_mode(id);
    
              auto result = client.Post(
                "/",
                std::move(req),
                std::move(resp)
              );
    
              // std::cout << ">> waiting for result " << id  << std::endl;
              auto r = result.get();
              req = std::move(r.Request);
              resp = std::move(r.Response);
              if (resp->error().size() != 0) {
                std::cout << ">> read failed with: " << resp->error() << std::endl;
    
              } else {
                // std::cout << ">> result " << resp->code()  << std::endl;
                if (resp->code() != id) {
                  std::cout << ">> id do not match" << std::endl;
                }
              }
            }
          }
        );
      }
    
      // client.Close();
      for (auto& th : threads) {
        th.join();
      }
    
      auto end = std::chrono::high_resolution_clock::now();
      auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
      fmt::print("elapsed: {}ms\n", elapsed.count());
    }