Page MenuHomePhorge

No OneTemporary

Size
24 KB
Referenced Files
None
Subscribers
None
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..cf0a698
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+
+*~
+build
+\#*
+.#*
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..444bf43
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,12 @@
+[submodule "external/lager"]
+ path = external/lager
+ url = https://github.com/arximboldi/lager.git
+[submodule "external/zug"]
+ path = external/zug
+ url = https://github.com/arximboldi/zug.git
+[submodule "external/immer"]
+ path = external/immer
+ url = https://github.com/arximboldi/immer.git
+[submodule "external/json"]
+ path = external/json
+ url = https://github.com/nlohmann/json.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..fb3e053
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,59 @@
+cmake_minimum_required(VERSION 3.8)
+
+if(NOT DEFINED PROJECT_NAME)
+ if(NOT DEFINED libkazv_INSTALL_HEADERS)
+ set(libkazv_INSTALL_HEADERS ON)
+ endif()
+endif()
+
+project(libkazv)
+
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
+
+# Build shared libraries by default
+if(NOT DEFINED BUILD_SHARED_LIBS)
+ set(BUILD_SHARED_LIBS ON)
+endif()
+
+include(FetchContent)
+set(USE_SYSTEM_CURL ON)
+set(BUILD_CPR_TESTS OFF)
+FetchContent_Declare(cpr GIT_REPOSITORY https://github.com/whoshuu/cpr.git GIT_TAG c8d33915dbd88ad6c92b258869b03aba06587ff9) # the commit hash for 1.5.0
+FetchContent_MakeAvailable(cpr)
+
+FetchContent_Declare(Catch2 GIT_REPOSITORY https://github.com/catchorg/Catch2 GIT_TAG v2.13.0)
+FetchContent_MakeAvailable(Catch2)
+
+set(JSON_BuildTests OFF)
+FetchContent_Declare(nlohmann_json GIT_REPOSITORY https://github.com/nlohmann/json GIT_TAG v3.9.1)
+FetchContent_MakeAvailable(nlohmann_json)
+
+set(immer_BUILD_TESTS OFF)
+set(immer_BUILD_EXAMPLES OFF)
+set(immer_BUILD_DOCS OFF)
+set(immer_BUILD_EXTRAS OFF)
+FetchContent_Declare(immer GIT_REPOSITORY https://github.com/arximboldi/immer GIT_TAG 2076affd9d814afc019ba8cd8c2b18a6c79c9589)
+FetchContent_MakeAvailable(immer)
+
+set(zug_BUILD_TESTS OFF)
+set(zug_BUILD_EXAMPLES OFF)
+set(zug_BUILD_DOCS OFF)
+FetchContent_Declare(zug GIT_REPOSITORY https://github.com/arximboldi/zug GIT_TAG 0bf540906165143eb8b195284c588be29438a16b)
+FetchContent_MakeAvailable(zug)
+
+# Do not let the option()s override variables here
+cmake_policy(SET CMP0077 NEW)
+set(lager_BUILD_TESTS OFF)
+set(lager_BUILD_EXAMPLES OFF)
+set(lager_BUILD_DOCS OFF)
+set(lager_EMBED_RESOURCES_PATH OFF)
+FetchContent_Declare(lager GIT_REPOSITORY https://github.com/arximboldi/lager GIT_TAG a112eed88789bb2986b7924b5b1e71c8a410f81a)
+FetchContent_MakeAvailable(lager)
+
+
+
+option(libkazv_BUILD_TESTS "Build tests" ON)
+option(libkazv_BUILD_EXAMPLES "Build examples" ON)
+
+add_subdirectory(src)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000..0c2ad61
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,53 @@
+
+include_directories(api .)
+
+set(libkazv_SRCS
+# api/wellknown.cpp
+ api/basejob.cpp
+ api/login.cpp
+ client/client.cpp
+ )
+
+add_library(kazv ${libkazv_SRCS})
+add_library(libkazv::kazv ALIAS kazv)
+
+target_link_libraries(kazv
+ PUBLIC cpr::cpr
+ PUBLIC nlohmann_json::nlohmann_json
+ PUBLIC immer
+ PUBLIC zug
+ PUBLIC lager)
+target_include_directories(kazv
+ INTERFACE
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/kazv>
+ )
+
+install(
+ TARGETS kazv
+
+ LIBRARY
+ )
+
+if(libkazv_INSTALL_HEADERS)
+ install(
+ DIRECTORY
+ ${CMAKE_CURRENT_SOURCE_DIR}/
+
+ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/kazv"
+
+ FILES_MATCHING PATTERN "*.hpp"
+
+ PATTERN "tests" EXCLUDE
+ )
+endif()
+
+# export(TARGETS kazv)
+
+if(libkazv_BUILD_TESTS)
+ add_subdirectory(tests)
+endif()
+
+if(libkazv_BUILD_EXAMPLES)
+ add_subdirectory(examples)
+endif()
diff --git a/src/api/basejob.cpp b/src/api/basejob.cpp
new file mode 100644
index 0000000..fb251b8
--- /dev/null
+++ b/src/api/basejob.cpp
@@ -0,0 +1,116 @@
+
+#include <cpr/cpr.h>
+#include <lager/util.hpp>
+
+#include "basejob.hpp"
+
+namespace Kazv
+{
+ BaseJob::Get BaseJob::GET{};
+ BaseJob::Post BaseJob::POST{};
+ BaseJob::Put BaseJob::PUT{};
+ BaseJob::Delete BaseJob::DELETE{};
+
+ struct BaseJob::Private
+ {
+ Private(std::string serverUrl,
+ std::string requestUrl,
+ Method method,
+ std::string token,
+ ReturnType returnType,
+ Body body);
+ std::string fullRequestUrl;
+ Method method;
+ ReturnType returnType;
+ cpr::Header header;
+ BytesBody body;
+ };
+
+ BaseJob::Private::Private(std::string serverUrl,
+ std::string requestUrl,
+ Method method,
+ std::string token,
+ ReturnType returnType,
+ Body body)
+ : fullRequestUrl(serverUrl + requestUrl)
+ , method(std::move(method))
+ , returnType(returnType)
+ , header()
+ , body()
+
+ {
+ if (token.size()) {
+ header["Authorization"] = "Bearer " + token;
+ }
+
+ if (isBodyJson(body)) {
+ JsonBody j = std::get<JsonBody>(std::move(body));
+ header["Content-Type"] = "application/json";
+ this->body = j.get().dump();
+ } else if (std::holds_alternative<BytesBody>(body)) {
+ BytesBody b = std::get<BytesBody>(std::move(body));
+ this->body = b;
+ }
+ }
+
+ BaseJob::BaseJob(std::string serverUrl,
+ std::string requestUrl,
+ Method method,
+ std::string token,
+ ReturnType returnType,
+ Body body)
+ : m_d(std::move(Private(serverUrl, requestUrl, method, token, returnType, body)))
+ {
+ }
+
+ auto BaseJob::fetch() const -> std::future<Response>
+ {
+ cpr::Url url{m_d->fullRequestUrl};
+ cpr::Body body(m_d->body);
+ cpr::Header header{m_d->header};
+
+ auto callback = [returnType = m_d->returnType](cpr::Response r) -> Response {
+ Body body = r.text;
+
+ if (returnType == ReturnType::Json) {
+ try {
+ body = JsonBody(std::move(json::parse(r.text)));
+ } catch (const json::exception &) {
+ // the response is not valid json
+ }
+ }
+
+ return { r.status_code, body };
+ };
+
+ return std::visit(lager::visitor{
+ [=](Get) {
+ return cpr::GetCallback(callback, url, header, body);
+ },
+ [=](Post) {
+ return cpr::PostCallback(callback, url, header, body);
+ },
+ [=](Put) {
+ return cpr::PutCallback(callback, url, header, body);
+ },
+ [=](Delete) {
+ return cpr::DeleteCallback(callback, url, header, body);
+ }
+ }, m_d->method);
+ }
+
+ bool BaseJob::shouldReturnJson() const
+ {
+ return m_d->returnType == ReturnType::Json;
+ };
+
+ std::string BaseJob::url() const
+ {
+ return m_d->fullRequestUrl;
+ };
+
+ JsonWrap jsonBody(const BaseJob::Response &res)
+ {
+ return std::get<JsonWrap>(res.body);
+ }
+}
diff --git a/src/api/basejob.hpp b/src/api/basejob.hpp
new file mode 100644
index 0000000..fa97302
--- /dev/null
+++ b/src/api/basejob.hpp
@@ -0,0 +1,76 @@
+
+#pragma once
+
+#include <variant>
+#include <tuple>
+#include <functional>
+#include <string>
+#include <immer/map.hpp>
+#include <immer/array.hpp>
+#include <future>
+
+#include "types.hpp"
+#include "descendent.hpp"
+
+namespace Kazv
+{
+ class BaseJob
+ {
+ public:
+ struct Get {};
+ struct Post {};
+ struct Put {};
+ struct Delete {};
+ using Method = std::variant<Get, Post, Put, Delete>;
+
+ static Get GET;
+ static Post POST;
+ static Put PUT;
+ static Delete DELETE;
+
+ using Query = immer::map<std::string, std::string>;
+
+ using BytesBody = Bytes;
+ using JsonBody = JsonWrap;
+ struct EmptyBody {};
+ using Body = std::variant<EmptyBody, JsonBody, BytesBody>;
+
+ static constexpr bool isBodyJson(const Body &body) {
+ return std::holds_alternative<JsonBody>(body);
+ };
+
+ using StatusCode = int;
+ struct Response {
+ StatusCode statusCode;
+ Body body;
+ };
+
+ constexpr bool success(const Response &res) const {
+ return res.statusCode < 300 && (!shouldReturnJson() || isBodyJson(res.body));
+ }
+
+ enum ReturnType {
+ Json,
+ Byte,
+ };
+
+ BaseJob(std::string serverUrl,
+ std::string requestUrl,
+ Method method,
+ std::string token = {},
+ ReturnType returnType = ReturnType::Json,
+ Body body = EmptyBody{});
+
+ std::future<Response> fetch() const;
+
+ bool shouldReturnJson() const;
+
+ std::string url() const;
+
+ private:
+ struct Private;
+ Descendent<Private> m_d;
+ };
+
+ JsonWrap jsonBody(const BaseJob::Response &res);
+}
diff --git a/src/api/constants.hpp b/src/api/constants.hpp
new file mode 100644
index 0000000..a6cfacf
--- /dev/null
+++ b/src/api/constants.hpp
@@ -0,0 +1,9 @@
+
+#include <string>
+
+namespace Kazv
+{
+ using namespace std::string_literals;
+ const std::string CLIENT_MAJOR_VERSION = "r0"s;
+ const std::string BASE_PATH = "/_matrix/client/"s + CLIENT_MAJOR_VERSION;
+}
diff --git a/src/api/login.cpp b/src/api/login.cpp
new file mode 100644
index 0000000..52c1575
--- /dev/null
+++ b/src/api/login.cpp
@@ -0,0 +1,47 @@
+
+#include "constants.hpp"
+#include "login.hpp"
+
+namespace Kazv
+{
+ GetLoginFlowsJob::GetLoginFlowsJob(std::string serverUrl)
+ : BaseJob(std::move(serverUrl), BASE_PATH + "/login"s, GET)
+ {
+ }
+
+
+ json loginDataToJson(std::string serverUrl,
+ std::string username,
+ std::string password,
+ std::optional<std::string> deviceName)
+ {
+ json j = json::object();
+ j["type"] = "m.login.password";
+ j["identifier"] = json::object();
+ j["identifier"]["type"] = "m.id.user";
+ j["identifier"]["user"] = std::move(username);
+ j["password"] = std::move(password);
+ j["initial_device_display_name"] = deviceName
+ ? std::move(deviceName.value())
+ : "libkazv"s;
+
+ return j;
+ }
+
+
+ LoginJob::LoginJob(std::string serverUrl,
+ std::string username,
+ std::string password,
+ std::optional<std::string> deviceName)
+ : BaseJob(serverUrl,
+ BASE_PATH + "/login"s,
+ POST,
+ std::string{},
+ ReturnType::Json,
+ JsonBody(loginDataToJson(serverUrl,
+ std::move(username),
+ std::move(password),
+ std::move(deviceName))))
+ {
+ }
+};
diff --git a/src/api/login.hpp b/src/api/login.hpp
new file mode 100644
index 0000000..8b6d92c
--- /dev/null
+++ b/src/api/login.hpp
@@ -0,0 +1,19 @@
+
+#include "basejob.hpp"
+
+namespace Kazv
+{
+ class GetLoginFlowsJob : public BaseJob
+ {
+ public:
+ GetLoginFlowsJob(std::string serverUrl);
+ };
+ class LoginJob : public BaseJob
+ {
+ public:
+ LoginJob(std::string serverUrl,
+ std::string username,
+ std::string password,
+ std::optional<std::string> deviceName);
+ };
+};
diff --git a/src/api/wellknown.cpp b/src/api/wellknown.cpp
new file mode 100644
index 0000000..34a0211
--- /dev/null
+++ b/src/api/wellknown.cpp
@@ -0,0 +1,10 @@
+
+#include "wellknown.hpp"
+
+namespace Kazv
+{
+ GetWellKnownJob::GetWellKnownJob(std::string serverUrl)
+ : BaseJob(std::move(serverUrl), "/.well-known/matrix/client", GET)
+ {
+ }
+}
diff --git a/src/api/wellknown.hpp b/src/api/wellknown.hpp
new file mode 100644
index 0000000..86e87e6
--- /dev/null
+++ b/src/api/wellknown.hpp
@@ -0,0 +1,14 @@
+
+#pragma once
+
+#include "basejob.hpp"
+#include "types.hpp"
+
+namespace Kazv
+{
+ class GetWellKnownJob : public BaseJob
+ {
+ public:
+ GetWellKnownJob(std::string serverUrl);
+ };
+}
diff --git a/src/client/client.cpp b/src/client/client.cpp
new file mode 100644
index 0000000..21e6cff
--- /dev/null
+++ b/src/client/client.cpp
@@ -0,0 +1,89 @@
+
+#include <lager/util.hpp>
+#include <lager/context.hpp>
+#include <functional>
+
+#include "client.hpp"
+#include "api/login.hpp"
+#include "types.hpp"
+#include "iostream"
+
+namespace Kazv
+{
+ lager::effect<Client::Action> loginEffect(Client::LoginAction a)
+ {
+ return
+ [=](auto &&ctx) {
+ LoginJob job(a.serverUrl,
+ a.username,
+ a.password,
+ a.deviceName);
+ auto res = job.fetch();
+ std::cout << "Result validity: " << res.valid() << std::endl;
+ auto r = res.get();
+ if (job.success(r)) {
+ std::cout << "Job success" << std::endl;
+ const json &j = jsonBody(r).get();
+ try {
+ std::string serverUrl = j.contains("well_known")
+ ? j.at("well_known").at("m.homeserver").at("base_url").get<std::string>()
+ : a.serverUrl;
+ ctx.dispatch(Client::LoadUserInfoAction{
+ serverUrl,
+ j.at("user_id"),
+ j.at("access_token"),
+ j.at("device_id"),
+ /* loggedIn = */ true
+ });
+ } catch (const json::out_of_range &e) {
+ std::cout << "Bad login" << e.what() << std::endl;
+ ctx.dispatch(Error::SetErrorAction{e.what()});
+ }
+ }
+ };
+ }
+
+ lager::effect<Client::Action> logoutEffect(Client::LogoutAction a)
+ {
+ return
+ [=](auto &&ctx) {
+ ctx.dispatch(Client::LoadUserInfoAction{
+ ""s,
+ ""s,
+ ""s,
+ ""s,
+ /* loggedIn = */ true
+ });
+ };
+ }
+
+
+ auto Client::update(Client m, Action a) -> Result
+ {
+ std::cout << "Client::update()" << std::endl;
+ return
+ std::visit(lager::visitor{
+ [=](Error::Action a) mutable -> Result {
+ m.error = Error::update(m.error, a);
+ return {std::move(m), lager::noop};
+ },
+ [=](LoginAction a) mutable -> Result {
+ return {std::move(m), loginEffect(std::move(a))};
+ },
+ [=](LogoutAction a) mutable -> Result {
+ return {std::move(m), logoutEffect(std::move(a))};
+ },
+ [=](LoadUserInfoAction a) mutable -> Result {
+ std::cout << "LoadUserInfoAction: " << a.userId << std::endl;
+ // Need to use set()s
+ Client newClient{a.serverUrl,
+ a.userId,
+ a.token,
+ a.deviceId,
+ a.loggedIn,
+ Error::NoError{}};
+ return { std::move(newClient), lager::noop };
+ },
+ }, std::move(a));
+ }
+}
diff --git a/src/client/client.hpp b/src/client/client.hpp
new file mode 100644
index 0000000..b59d925
--- /dev/null
+++ b/src/client/client.hpp
@@ -0,0 +1,48 @@
+
+#pragma once
+
+#include <tuple>
+#include <variant>
+#include <string>
+
+#include <lager/context.hpp>
+
+#include "error.hpp"
+
+namespace Kazv
+{
+ struct Client
+ {
+ std::string serverUrl;
+ std::string userId;
+ std::string token;
+ std::string deviceId;
+ bool loggedIn;
+ Error error;
+
+ struct LoginAction {
+ std::string serverUrl;
+ std::string username;
+ std::string password;
+ std::optional<std::string> deviceName;
+ };
+
+ struct LoadUserInfoAction {
+ std::string serverUrl;
+ std::string userId;
+ std::string token;
+ std::string deviceId;
+ bool loggedIn;
+ };
+
+ struct LogoutAction {};
+
+ using Action = std::variant<LoginAction,
+ LogoutAction,
+ LoadUserInfoAction,
+ Error::Action
+ >;
+ using Result = std::pair<Client, lager::effect<Action>>;
+ static Result update(Client m, Action a);
+ };
+}
diff --git a/src/client/discovery.hpp b/src/client/discovery.hpp
new file mode 100644
index 0000000..887a2e0
--- /dev/null
+++ b/src/client/discovery.hpp
@@ -0,0 +1,26 @@
+
+#include "types.hpp"
+
+namespace Kazv
+{
+ struct Result {
+ Status status;
+ std::optional<std::string> homeserver;
+ std::optional<std::string> identityServer;
+ };
+
+ Result parseHomeserver(Response r);
+
+ auto GetWellKnownJob::parse(Response r) -> Result
+ {
+ if (r.statusCode == 404) {
+ return Result{SUCC};
+ } else if (r.statusCode != 200
+ || !isBodyJson(r.body)) {
+ return Result{FAIL};
+ } else {
+ return Result{FAIL};
+ }
+ }
+
+}
diff --git a/src/client/error.hpp b/src/client/error.hpp
new file mode 100644
index 0000000..ad80e29
--- /dev/null
+++ b/src/client/error.hpp
@@ -0,0 +1,31 @@
+
+#include "types.hpp"
+#include <variant>
+
+namespace Kazv
+{
+ struct Error
+ {
+ struct NoError {};
+ using JsonError = JsonWrap;
+ std::variant<NoError, JsonError, std::string> error;
+
+ struct SetErrorAction {
+ std::variant<NoError, JsonError, std::string> error;
+ };
+
+ using Action = std::variant<SetErrorAction>;
+
+ static inline Error update(Error e, Action a) {
+ return Error{std::get<SetErrorAction>(a).error};
+ }
+
+ constexpr bool hasError() const {
+ return !std::holds_alternative<NoError>(error);
+ }
+
+ constexpr bool isJson() const {
+ return !std::holds_alternative<JsonError>(error);
+ }
+ };
+};
diff --git a/src/descendent.hpp b/src/descendent.hpp
new file mode 100644
index 0000000..973531d
--- /dev/null
+++ b/src/descendent.hpp
@@ -0,0 +1,46 @@
+
+#pragma once
+
+#include <memory>
+
+namespace Kazv
+{
+ template<typename T>
+ class Descendent
+ {
+ struct concept
+ {
+ virtual ~concept() = default;
+ virtual const T *ptr() const = 0;
+ virtual T *ptr() = 0;
+ virtual std::unique_ptr<concept> clone() const = 0;
+ };
+ template<typename U>
+ struct model : public concept
+ {
+ model(U x) : instance(std::move(x)) {}
+ const T *ptr() const { return &instance; }
+ T *ptr() { return &instance; }
+ // or std::unique_ptr<model<U> >(new model<U>(U(instance))) if you do not have C++14
+ std::unique_ptr<concept> clone() const { return std::make_unique<model<U> >(U(instance)); }
+ U instance;
+ };
+
+ std::unique_ptr<concept> m_d;
+ public:
+ template<typename U>
+ Descendent(U x) : m_d(std::make_unique<model<U> >(std::move(x))) {}
+
+ Descendent(const Descendent & that) : m_d(std::move(that.m_d->clone())) {}
+ Descendent(Descendent && that) : m_d(std::move(that.m_d)) {}
+
+ Descendent & operator=(const Descendent &that) { Descendent t(that); *this = std::move(t); return *this; }
+ Descendent & operator=(Descendent && that) { m_d = std::move(that.m_d); return *this; }
+
+ const T *data() const { return m_d->ptr(); }
+ const T *constData() const { return m_d->ptr(); }
+ T *data() { return m_d->ptr(); }
+ const T *operator->() const { return m_d->ptr(); }
+ T *operator->() { return m_d->ptr(); }
+ };
+}
diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt
new file mode 100644
index 0000000..bd2fabc
--- /dev/null
+++ b/src/examples/CMakeLists.txt
@@ -0,0 +1,9 @@
+
+add_executable(basicexample
+ basic/main.cpp)
+
+target_link_libraries(basicexample
+ PRIVATE kazv
+ PRIVATE immer
+ PRIVATE zug
+ PRIVATE lager)
diff --git a/src/examples/basic/main.cpp b/src/examples/basic/main.cpp
new file mode 100644
index 0000000..0b1af8c
--- /dev/null
+++ b/src/examples/basic/main.cpp
@@ -0,0 +1,31 @@
+
+#include <string>
+#include <iostream>
+#include <lager/store.hpp>
+#include <lager/event_loop/manual.hpp>
+
+#include <client/client.hpp>
+
+using namespace std::string_literals;
+
+int main()
+{
+ auto store = lager::make_store<Kazv::Client::Action>(
+ Kazv::Client{},
+ &Kazv::Client::update,
+ lager::with_manual_event_loop{});
+
+ std::string homeserver;
+ std::string username;
+ std::string password;
+ std::cout << "Homeserver: ";
+ std::getline(std::cin, homeserver);
+ std::cout << "Username: ";
+ std::getline(std::cin, username);
+ std::cout << "Password: ";
+ std::getline(std::cin, password);
+ store.dispatch(Kazv::Client::LoginAction{homeserver, username, password, "libkazv basic example"s});
+
+ std::cout << "Token: " << store.get().token << std::endl;
+
+}
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
new file mode 100644
index 0000000..bf55846
--- /dev/null
+++ b/src/tests/CMakeLists.txt
@@ -0,0 +1,16 @@
+
+
+include(CTest)
+
+add_executable(basejobtest
+ testallapi.cpp
+
+ basejobtest.cpp
+ )
+target_link_libraries(basejobtest
+ PRIVATE Catch2::Catch2
+ PRIVATE kazv
+ PRIVATE nlohmann_json::nlohmann_json
+ PRIVATE immer
+ PRIVATE lager
+ PRIVATE zug)
diff --git a/src/tests/basejobtest.cpp b/src/tests/basejobtest.cpp
new file mode 100644
index 0000000..3cda132
--- /dev/null
+++ b/src/tests/basejobtest.cpp
@@ -0,0 +1,27 @@
+
+#include <catch2/catch.hpp>
+
+#include <iostream>
+#include <future>
+
+#include <basejob.hpp>
+#include "tests.hpp"
+
+using namespace Kazv;
+
+TEST_CASE("Base job should fetch correctly", "[basejob]")
+{
+ BaseJob job(TEST_SERVER_URL, "/.well-known/matrix/client", BaseJob::Get{});
+
+ auto futureResponse = job.fetch();
+ BaseJob::Response r = futureResponse.get();
+
+ if (r.statusCode == 200) {
+ REQUIRE( BaseJob::isBodyJson(r.body) );
+
+ json j = std::get<BaseJob::JsonBody>(r.body).get();
+
+ REQUIRE_NOTHROW( (j["m.homeserver"]["base_url"]) );
+ REQUIRE( (j["m.homeserver"]["base_url"].size() > 0) );
+ }
+}
diff --git a/src/tests/testallapi.cpp b/src/tests/testallapi.cpp
new file mode 100644
index 0000000..621d513
--- /dev/null
+++ b/src/tests/testallapi.cpp
@@ -0,0 +1,3 @@
+
+#define CATCH_CONFIG_MAIN
+#include <catch2/catch.hpp>
diff --git a/src/tests/tests.hpp b/src/tests/tests.hpp
new file mode 100644
index 0000000..4ffc17b
--- /dev/null
+++ b/src/tests/tests.hpp
@@ -0,0 +1,9 @@
+
+#pragma once
+#include <string>
+
+#ifndef TEST_SERVER
+#define TEST_SERVER "https://matrix.org"
+#endif
+
+const std::string TEST_SERVER_URL{TEST_SERVER};
diff --git a/src/types.hpp b/src/types.hpp
new file mode 100644
index 0000000..499faa8
--- /dev/null
+++ b/src/types.hpp
@@ -0,0 +1,33 @@
+
+#pragma once
+#include <string>
+#include <nlohmann/json.hpp>
+#include <immer/array.hpp>
+
+namespace Kazv
+{
+ using json = nlohmann::json;
+
+ using Bytes = std::string;
+
+ enum Status : bool
+ {
+ FAIL,
+ SUCC,
+ };
+
+ class JsonWrap
+ {
+ // Cannot use box here, because it causes the resulting json
+ // to be wrapped into an array.
+ // https://github.com/arximboldi/immer/issues/155
+ immer::array<json> m_d;
+ public:
+ JsonWrap(json&& j) : m_d(1, std::move(j)) {}
+ JsonWrap(const json& j) : m_d(1, j) {}
+
+ auto get() const { return m_d.at(0); }
+ };
+
+ using namespace std::string_literals;
+}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Oct 8, 10:31 PM (11 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1784328
Default Alt Text
(24 KB)

Event Timeline