Page MenuHomePhorge

No OneTemporary

Authored By
Unknown
Size
41 KB
Referenced Files
None
Subscribers
None
diff --git a/.gitignore b/.gitignore
index 7f7546e..d3e9d80 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,10 +1,11 @@
/target
python/__pycache__
python/tests/__pycache__
javascript/node_modules
javascript/yarn-error.log
javascript/yarn.lock
cpp/*-test
cpp/objects
.ccls-cache
cpp/src/lib.rs
+build
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 76b4f72..0f98b19 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,44 +1,36 @@
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "trigger"'
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: never
- if: $CI_COMMIT_BRANCH
- if: '$CI_COMMIT_TAG !~ /^phabricator\//'
stages:
- build
.build:
stage: build
image: docker.io/ubuntu:24.04
script:
- apt-get update
- DEBIAN_FRONTEND=noninteractive apt-get -y upgrade
- - DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends rustup build-essential g++ libolm-dev libboost-json-dev wget cmake ca-certificates
+ - DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends rustup build-essential g++ libolm-dev libboost-json-dev wget cmake ca-certificates catch2 corrosion
- rustup default stable
- # catch2 is broken in ubuntu, see https://bugs.launchpad.net/ubuntu/+source/catch2/+bug/2081647
- - wget https://github.com/catchorg/Catch2/archive/v3.3.2.tar.gz -O catch2.tar.gz
- - tar -xf catch2.tar.gz
- - cd Catch2-*
- - mkdir build && cd build && \
- - cmake .. -DCATCH_ENABLE_WERROR=OFF -DBUILD_TESTING=OFF
- - make -j$(($(nproc) / 2)) install
- - cd ../..
- - rm -rf Catch2-* catch2.tar.gz
- - cd cpp
- - mv -v build.rs build.rs.orig
- - grep -v 'cargo::rerun-if-changed' build.rs.orig > build.rs
- - make BUILD_TYPE="$BUILD_TYPE" test
+ - mkdir build
+ - cd build
+ - cmake .. -DCMAKE_BUILD_TYPE="$BUILD_TYPE"
+ - make -j$(($(nproc) / 2))
+ - CTEST_OUTPUT_ON_FAILURE=ON make test
build:release:
extends:
- .build
before_script:
- - BUILD_TYPE=release
+ - BUILD_TYPE=Release
build:debug:
extends:
- .build
before_script:
- - BUILD_TYPE=debug
+ - BUILD_TYPE=Debug
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..ae0a4eb
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,66 @@
+
+cmake_minimum_required(VERSION 3.23)
+
+project(vodozemac-bindings)
+
+include(GNUInstallDirs)
+include(CTest)
+find_package(Perl REQUIRED)
+find_package(Corrosion REQUIRED)
+
+# corrosion_import_crate requires that lib.rs exist, so we must generate it right now when configuring
+message(STATUS "Generating lib.rs")
+execute_process(COMMAND "${PERL_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/cpp/inject-maybe"
+ "${CMAKE_SOURCE_DIR}/cpp/src/lib.rs.in" "${CMAKE_BINARY_DIR}/vodozemac.lib.rs"
+ ERROR_FILE "${CMAKE_BINARY_DIR}/vodozemac.lib.rs.log"
+ COMMAND_ERROR_IS_FATAL ANY)
+# Use a temporary file and copy it into place to avoid unnecessarily updating it
+configure_file("${CMAKE_BINARY_DIR}/vodozemac.lib.rs" "${CMAKE_SOURCE_DIR}/cpp/src/lib.rs" COPYONLY)
+
+corrosion_import_crate(MANIFEST_PATH cpp/Cargo.toml)
+
+add_library(vodozemac-shared SHARED)
+add_custom_command(OUTPUT "${CMAKE_BINARY_DIR}/vodozemac.h"
+ COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_BINARY_DIR}/cargo/build/${Rust_CARGO_TARGET}/cxxbridge/vodozemac/src/lib.rs.h" "${CMAKE_BINARY_DIR}/vodozemac.h"
+ VERBATIM
+ DEPENDS vodozemac-static
+)
+set(vodozemac_HEADERS "${CMAKE_BINARY_DIR}/vodozemac.h")
+target_sources(
+ vodozemac-shared
+ PRIVATE
+ FILE_SET HEADERS FILES ${vodozemac_HEADERS})
+set_target_properties(vodozemac-shared
+ PROPERTIES
+ LINKER_LANGUAGE CXX
+ OUTPUT_NAME vodozemac
+ EXPORT_NAME vodozemac
+ VERSION 1.0.0
+ SOVERSION 4
+)
+target_link_libraries(vodozemac-shared PRIVATE "$<LINK_LIBRARY:WHOLE_ARCHIVE,vodozemac-static>")
+target_include_directories(vodozemac-shared INTERFACE
+ $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+)
+install(FILES ${vodozemac_HEADERS} TYPE INCLUDE RENAME vodozemac.h)
+install(TARGETS vodozemac-shared EXPORT vodozemacTargets LIBRARY)
+
+set(ConfigPackageLocation ${CMAKE_INSTALL_LIBDIR}/cmake/vodozemac)
+
+install(
+ EXPORT vodozemacTargets
+ NAMESPACE vodozemac::
+ DESTINATION ${ConfigPackageLocation}
+)
+
+install(
+ FILES cmake/vodozemacConfig.cmake
+ DESTINATION ${ConfigPackageLocation})
+
+if(BUILD_TESTING)
+ find_package(Catch2 REQUIRED)
+ find_package(Boost REQUIRED COMPONENTS json)
+ find_package(Olm REQUIRED)
+ add_subdirectory(cpp/tests)
+endif()
diff --git a/cmake/vodozemacConfig.cmake b/cmake/vodozemacConfig.cmake
new file mode 100644
index 0000000..3b2adb0
--- /dev/null
+++ b/cmake/vodozemacConfig.cmake
@@ -0,0 +1,2 @@
+
+include("${CMAKE_CURRENT_LIST_DIR}/vodozemacTargets.cmake")
diff --git a/cpp/Makefile b/cpp/Makefile
deleted file mode 100644
index a06fd29..0000000
--- a/cpp/Makefile
+++ /dev/null
@@ -1,117 +0,0 @@
-
-.PHONY: all dynamic-lib test install
-
-BUILD_TYPE := debug
-ifeq ($(BUILD_TYPE), release)
-CARGO_ARGS = --release
-else
-CARGO_ARGS =
-endif
-ifneq ($(CARGO_TARGET),)
-CARGO_ARGS += --target $(CARGO_TARGET)
-endif
-
-VERSION = 1.0.0
-SOVERSION = 4
-
-ifeq ($(CARGO_TARGET),)
-TARGET_DIR = ../target/$(BUILD_TYPE)
-else
-TARGET_DIR = ../target/$(CARGO_TARGET)/$(BUILD_TYPE)
-endif
-CXXBRIDGE_DIR = $(TARGET_DIR)/../cxxbridge
-STATIC_LIB = $(TARGET_DIR)/libvodozemac.a
-ifeq ($(OS), Windows_NT)
-SHARED_LIB_NAME = libvodozemac.dll
-else
-UNAME_S := $(shell uname -s)
-ifeq ($(UNAME_S),Darwin)
-SHARED_LIB_NAME = libvodozemac.dylib
-else
-SHARED_LIB_NAME = libvodozemac.so
-endif
-endif
-SHARED_LIB_PREFIX = $(TARGET_DIR)/$(SHARED_LIB_NAME)
-SHARED_LIBS = $(SHARED_LIB_PREFIX) $(SHARED_LIB_PREFIX).$(VERSION) $(SHARED_LIB_PREFIX).$(SOVERSION)
-
-# The list of libraries are obtained by running
-# `cargo rustc -- --print native-static-libs`.
-# Unfortunately, the output format is really hostile to automatically generating the list on the fly.
-ifeq ($(OS), Windows_NT)
-SHARED_LIB_LDFLAGS = -lbcrypt -ladvapi32 -lstdc++ -lkernel32 -ladvapi32 -lntdll -luserenv -lws2_32 -lkernel32 -Wl,--out-implib,$(SHARED_LIB_PREFIX).a
-else ifeq ($(UNAME_S),Darwin)
-SHARED_LIB_LDFLAGS = -lc++
-else ifeq ($(CARGO_TARGET),aarch64-linux-android)
-SHARED_LIB_LDFLAGS = -lc -lm -lc++_shared -ldl -llog -lunwind -ldl -lm -lc
-else
-SHARED_LIB_LDFLAGS = -lstdc++ -lgcc_s -lutil -lrt -lpthread -lm -ldl -lc
-endif
-
-HEADER = $(CXXBRIDGE_DIR)/vodozemac/src/lib.rs.h
-SOURCES = src/account.rs src/group_sessions.rs src/lib.rs src/sas.rs src/session.rs src/types.rs src/maybe.rs build.rs vodozemac_maybe_derive/src/lib.rs
-
-all: dynamic-lib
-
-CXX ?= c++
-LN ?= ln
-INSTALL ?= install
-CP ?= cp
-PERL ?= perl
-CARGO ?= cargo
-
-# Packagers may need to override them all.
-PREFIX = /usr/local
-DESTDIR =
-LIBDIR = $(PREFIX)/lib
-INCLUDEDIR = $(PREFIX)/include
-
-src/lib.rs: src/lib.rs.in inject-maybe
- $(PERL) ./inject-maybe < src/lib.rs.in > src/lib.rs
-
-$(STATIC_LIB): $(SOURCES)
- $(CARGO) build $(CARGO_ARGS)
-
-dynamic-lib: $(SHARED_LIB_PREFIX)
-
-$(SHARED_LIB_PREFIX).$(SOVERSION): $(SHARED_LIB_PREFIX).$(VERSION)
- $(LN) -sfv $(SHARED_LIB_NAME).$(VERSION) $(SHARED_LIB_PREFIX).$(SOVERSION)
-
-$(SHARED_LIB_PREFIX): $(SHARED_LIB_PREFIX).$(SOVERSION)
- $(LN) -sfv $(SHARED_LIB_NAME).$(SOVERSION) $(SHARED_LIB_PREFIX)
-
-$(SHARED_LIB_PREFIX).$(VERSION): $(STATIC_LIB)
-ifeq ($(UNAME_S),Darwin)
- $(CXX) -Wl,-force_load,$(STATIC_LIB) $(SHARED_LIB_LDFLAGS) -dynamiclib -fPIC -Wl,-install_name,@rpath/$(SHARED_LIB_NAME).$(SOVERSION) -o $(SHARED_LIB_PREFIX).$(VERSION)
-else
- $(CXX) -Wl,--whole-archive $(STATIC_LIB) -Wl,--no-whole-archive $(SHARED_LIB_LDFLAGS) -shared -fPIC -Wl,-soname=$(SHARED_LIB_NAME) -o $(SHARED_LIB_PREFIX).$(VERSION)
-endif
-
-TEST_CXXFLAGS = -Wall -g -std=c++17 -I $(CXXBRIDGE_DIR)
-TEST_LDFLAGS = -lCatch2Main -lCatch2 -lolm -lboost_json \
- -L $(TARGET_DIR) -l vodozemac -ldl -Wl,-rpath,$(TARGET_DIR) \
- -L /usr/local/lib -Wl,-rpath,/usr/local/lib
-
-TEST_DEPS = $(SHARED_LIB_PREFIX).$(VERSION) tests/util.hpp
-TESTS_EXCEPT = account-test session-test sas-test group-session-test
-TESTS_NOEXCEPT = $(TESTS_EXCEPT:-test=-noexcept-test)
-TESTS = $(TESTS_EXCEPT) $(TESTS_NOEXCEPT)
-
-%-test: tests/%.cpp $(TEST_DEPS)
- $(CXX) $(TEST_CXXFLAGS) -DVODOZEMAC_TEST_EXCEPTIONS=1 -fexceptions $< $(TEST_LDFLAGS) -o $@
-
-%-noexcept-test: tests/%.cpp $(TEST_DEPS)
- $(CXX) $(TEST_CXXFLAGS) -DVODOZEMAC_TEST_EXCEPTIONS=0 -fno-exceptions $< $(TEST_LDFLAGS) -o $@
-
-test: $(TESTS)
- for i in $^; do ./$$i || exit 1; done
-
-install:
- $(INSTALL) -d $(DESTDIR)$(INCLUDEDIR) $(DESTDIR)$(LIBDIR)
- $(INSTALL) -m644 $(STATIC_LIB) $(DESTDIR)$(LIBDIR)
- $(INSTALL) -m755 $(SHARED_LIB_PREFIX).$(VERSION) $(DESTDIR)$(LIBDIR)
-ifeq ($(OS), Windows_NT)
- $(INSTALL) -m755 $(SHARED_LIB_PREFIX).a $(DESTDIR)$(LIBDIR)
-endif
- $(LN) -sfv $(SHARED_LIB_NAME).$(VERSION) $(DESTDIR)$(LIBDIR)/$(SHARED_LIB_NAME).$(SOVERSION)
- $(LN) -sfv $(SHARED_LIB_NAME).$(SOVERSION) $(DESTDIR)$(LIBDIR)/$(SHARED_LIB_NAME)
- $(CP) $(HEADER) $(DESTDIR)$(INCLUDEDIR)/vodozemac.h
diff --git a/cpp/inject-maybe b/cpp/inject-maybe
index 11e7bd0..3df8d77 100755
--- a/cpp/inject-maybe
+++ b/cpp/inject-maybe
@@ -1,74 +1,87 @@
#!/usr/bin/env perl
use strict;
sub getMaybeTypeId
{
my ($type) = @_;
if ($type eq '()') {
return 'MaybeOfNone';
}
for ($type) {
s/[^a-zA-Z0-9_]//g;
return "MaybeOf$_";
}
};
my %registeredTypes = ();
sub genTypedef
{
my ($type) = @_;
my $maybeType = getMaybeTypeId($type);
return "type $maybeType = Maybe<$type>;\n";
}
sub genMaybe
{
my ($type) = @_;
my $maybeType = getMaybeTypeId($type);
return <<"EOF";
#[namespace = "vodozemac::maybe"]
extern "Rust" {
type $maybeType;
fn is_valid(self: &$maybeType) -> bool;
fn has_value(self: &$maybeType) -> bool;
fn take_value(self: &mut $maybeType) -> $type;
fn take_error(self: &mut $maybeType) -> String;
}
EOF
}
my $funcName = '';
my $funcDecl = '';
my $output = '';
-while (<STDIN>) {
+my $in;
+if (length $ARGV[0]) {
+ open $in, '<', $ARGV[0] or die "Cannot open input file: $!\n";
+} else {
+ $in = \*STDIN;
+}
+my $out;
+if (length $ARGV[1]) {
+ open $out, '>', $ARGV[1] or die "Cannot open output file: $!\n";
+} else {
+ $out = \*STDOUT;
+}
+
+while (<$in>) {
$output .= $_;
if (/fn ([a-z_0-9]+)\(/) {
$funcName = $1;
print STDERR "Func name: $funcName\n";
s/fn ([a-z_0-9]+)\(/fn ${1}_noexcept(/;
$funcDecl = $_;
} else {
$funcDecl .= $_;
}
if (/-> Result<(.+)>;/) {
my $type = $1;
my $maybeType = getMaybeTypeId($type);
print STDERR "Found result type: '$type' -> '$maybeType'\n";
$registeredTypes{$type} = 1;
s/-> Result<\Q$type\E>;/-> Box<$maybeType>;/ for $funcDecl;
$output .= $funcDecl;
}
}
my $generatedTypedef = join '', map genTypedef($_), keys(%registeredTypes);
my $generatedMaybe = join '', map genMaybe($_), keys(%registeredTypes);
s{// gen-typedef-place\n}{$generatedTypedef} for $output;
s{// gen-maybe-place\n}{$generatedMaybe} for $output;
-print $output;
+print {$out} $output;
diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt
new file mode 100644
index 0000000..4bae54e
--- /dev/null
+++ b/cpp/tests/CMakeLists.txt
@@ -0,0 +1,21 @@
+function(vodozemac_add_test testname source)
+ add_executable("${testname}" "${source}")
+ target_link_libraries("${testname}"
+ PRIVATE Catch2::Catch2WithMain
+ Boost::json
+ Olm::Olm
+ vodozemac-shared)
+ add_test("${testname}" "${testname}")
+endfunction()
+
+function(vodozemac_add_tests)
+ foreach(testname ${ARGN})
+ vodozemac_add_test("${testname}" "${testname}.cpp")
+ target_compile_options("${testname}" PRIVATE -fexceptions)
+
+ vodozemac_add_test("${testname}-noexcept" "${testname}.cpp")
+ target_compile_options("${testname}-noexcept" PRIVATE -fno-exceptions)
+ endforeach()
+endfunction()
+
+vodozemac_add_tests(account group-session sas session)
diff --git a/cpp/tests/account.cpp b/cpp/tests/account.cpp
index 59e437e..ed39ddb 100644
--- a/cpp/tests/account.cpp
+++ b/cpp/tests/account.cpp
@@ -1,179 +1,179 @@
-#include "../../target/cxxbridge/vodozemac/src/lib.rs.h"
+#include <vodozemac.h>
#include <string>
#include <unordered_set>
#include <olm/olm.h>
#include <boost/json.hpp>
#include <catch2/catch_test_macros.hpp>
#include "util.hpp"
using namespace rust;
using namespace vodozemac;
TEST_CASE("AccountCreation", "[AccountTest]") {
auto alice = olm::new_account();
auto key = alice->ed25519_key();
auto encoded_key = key->to_base64();
REQUIRE(encoded_key.length() != 0);
}
TEST_CASE("OneTimeKeyGeneration", "[AccountTest]") {
auto alice = olm::new_account();
REQUIRE(alice->one_time_keys().size() == 0);
auto result = alice->generate_one_time_keys(10);
REQUIRE(result->created().size() == 10);
REQUIRE(alice->one_time_keys().size() == 10);
alice->mark_keys_as_published();
REQUIRE(alice->one_time_keys().size() == 0);
}
TEST_CASE("OneTimeKeysRemovedWhenTooMany", "[AccountTest]") {
auto alice = olm::new_account();
// Vodozemac will remove old one-time keys when the total number of generated one-time keys exceeds an internal constant.
// That internal constant is not a part of the public API, that's why we keep generating new keys until the first removal.
static constexpr std::size_t upper_bound = 1000000;
// The long variable names are needed for better error messages in case the test fails.
std::size_t total_number_of_generated_one_time_keys = 0;
std::size_t total_number_of_one_time_keys_removed = 0;
while (total_number_of_one_time_keys_removed == 0 && total_number_of_generated_one_time_keys < upper_bound) {
auto result = alice->generate_one_time_keys(alice->max_number_of_one_time_keys());
total_number_of_generated_one_time_keys += result->created().size();
total_number_of_one_time_keys_removed += result->removed().size();
}
SECTION("After generating really many one-time keys the oldest ones should be removed") {
REQUIRE(total_number_of_one_time_keys_removed > 0);
REQUIRE(alice->one_time_keys().size() + total_number_of_one_time_keys_removed == total_number_of_generated_one_time_keys);
}
}
TEST_CASE("FallbackKeyGeneration", "[AccountTest]") {
auto alice = olm::new_account();
REQUIRE(alice->fallback_key().size() == 0);
auto previous_fallback_key = alice->generate_fallback_key();
REQUIRE(alice->fallback_key().size() == 1);
REQUIRE(previous_fallback_key.size() == 0);
alice->mark_keys_as_published();
REQUIRE(alice->fallback_key().size() == 0);
}
TEST_CASE("FallbackKeyDeprecation", "[AccountTest]") {
auto alice = olm::new_account();
REQUIRE(alice->fallback_key().size() == 0);
auto previous_fallback_key = alice->generate_fallback_key();
REQUIRE(alice->fallback_key().size() == 1);
SECTION("When a fallback key is generated for the first time, there should not be any old fallback keys to remove.") {
REQUIRE(previous_fallback_key.size() == 0);
}
alice->mark_keys_as_published();
REQUIRE(alice->fallback_key().size() == 0);
// olm::Account stores up to two fallback keys.
// The old fallback key should not be removed, yet.
previous_fallback_key = alice->generate_fallback_key();
REQUIRE(alice->fallback_key().size() == 1);
SECTION("After a fallback key has been generated twice, the old fallback key should not be removed yet.") {
REQUIRE(previous_fallback_key.size() == 0);
}
alice->mark_keys_as_published();
REQUIRE(alice->fallback_key().size() == 0);
// Now we expect the old fallback key to be removed.
previous_fallback_key = alice->generate_fallback_key();
REQUIRE(alice->fallback_key().size() == 1);
SECTION("After a fallback key has been generated three times, the old fallback key should be removed.") {
REQUIRE(previous_fallback_key.size() == 1);
}
}
TEST_CASE("MaxKeysTest", "[AccountTest]") {
auto alice = olm::new_account();
auto max_keys = alice->max_number_of_one_time_keys();
REQUIRE(max_keys > 0);
REQUIRE(max_keys < 1000);
}
TEST_CASE("PickleTest", "[AccountTest]") {
auto alice = olm::new_account();
auto pickle = alice->pickle(PICKLE_KEY);
auto unpickled = REQUIRE_VODOZEMAC_OK(MAYBE_NOEXCEPT(olm::account_from_pickle)(pickle, PICKLE_KEY));
REQUIRE(alice->curve25519_key()->to_base64() ==
unpickled->curve25519_key()->to_base64());
}
TEST_CASE("PickleFromLibolmTest", "[AccountTest]") {
auto [data, alice] = new_olm_account();
auto random = gen_random(olm_account_generate_one_time_keys_random_length(alice, 10));
check_olm_error(olm_account_generate_one_time_keys(alice, 10, random.data(), random.size()));
auto pickle = std::string(olm_pickle_account_length(alice), '\0');
check_olm_error(olm_pickle_account(alice, OLM_PICKLE_KEY.data(), OLM_PICKLE_KEY.size(), pickle.data(), pickle.size()));
auto unpickled = REQUIRE_VODOZEMAC_OK(MAYBE_NOEXCEPT(olm::account_from_libolm_pickle)(pickle, Slice<const unsigned char>(OLM_PICKLE_KEY.data(), OLM_PICKLE_KEY.size())));
{
auto identity_keys = std::string(olm_account_identity_keys_length(alice), '\0');
check_olm_error(olm_account_identity_keys(alice, identity_keys.data(), identity_keys.size()));
auto parsed_keys = boost::json::parse(identity_keys).as_object();
auto curve25519_key = String(as_std_string(parsed_keys.at("curve25519").as_string()));
auto ed25519_key = String(as_std_string(parsed_keys.at("ed25519").as_string()));
REQUIRE(curve25519_key ==
unpickled->curve25519_key()->to_base64());
REQUIRE(ed25519_key ==
unpickled->ed25519_key()->to_base64());
}
{
auto one_time_keys = std::string(olm_account_one_time_keys_length(alice), '\0');
check_olm_error(olm_account_one_time_keys(alice, one_time_keys.data(), one_time_keys.size()));
auto parsed_keys = boost::json::parse(one_time_keys).as_object().at("curve25519").as_object();
// The key id will change from libolm to vodozemac, but the key themselves won't.
auto one_time_keys_set = std::unordered_set<std::string>();
for (const auto &pair : parsed_keys) {
one_time_keys_set.insert(as_std_string(pair.value().as_string()));
}
auto unpickled_one_time_keys = unpickled->one_time_keys();
auto unpickled_one_time_keys_set = std::unordered_set<std::string>();
for (const auto &k : unpickled_one_time_keys) {
unpickled_one_time_keys_set.insert(static_cast<std::string>(k.key->to_base64()));
}
REQUIRE(one_time_keys_set == unpickled_one_time_keys_set);
}
}
TEST_CASE("SignAndVerify", "[AccountTest]") {
auto alice = olm::new_account();
auto key = alice->ed25519_key();
std::string str = "{}";
auto signature = alice->sign(as_u8_slice(str));
REQUIRE_VODOZEMAC_OK(key->MAYBE_NOEXCEPT(verify)(as_u8_slice(str), *signature));
{
auto cloned_signature = types::ed25519_signature_from_base64(signature->to_base64());
REQUIRE_VODOZEMAC_OK(key->MAYBE_NOEXCEPT(verify)(as_u8_slice(str), *cloned_signature));
}
{
auto cloned_key = types::ed25519_key_from_base64(key->to_base64());
REQUIRE_VODOZEMAC_OK(cloned_key->MAYBE_NOEXCEPT(verify)(as_u8_slice(str), *signature));
}
std::string str2 = "{\"foo\": \"bar\"}";
auto signature2 = alice->sign(as_u8_slice(str2));
REQUIRE_VODOZEMAC_ERROR(key->MAYBE_NOEXCEPT(verify)(as_u8_slice(str2), *signature));
REQUIRE_VODOZEMAC_ERROR(key->MAYBE_NOEXCEPT(verify)(as_u8_slice(str), *signature2));
}
diff --git a/cpp/tests/group-session.cpp b/cpp/tests/group-session.cpp
index a014a3d..08961e3 100644
--- a/cpp/tests/group-session.cpp
+++ b/cpp/tests/group-session.cpp
@@ -1,239 +1,239 @@
-#include "../../target/cxxbridge/vodozemac/src/lib.rs.h"
+#include <vodozemac.h>
#include <olm/outbound_group_session.h>
#include <olm/inbound_group_session.h>
#include <catch2/catch_test_macros.hpp>
#include "util.hpp"
using namespace rust;
using namespace vodozemac;
struct SessionCreationResult {
Box<megolm::GroupSession> outbound;
Box<megolm::InboundGroupSession> inbound;
};
SessionCreationResult create_session() {
auto outbound = megolm::new_group_session();
auto session_key = outbound->session_key();
auto inbound = megolm::new_inbound_group_session(*session_key);
auto ret = SessionCreationResult{
std::move(outbound),
std::move(inbound),
};
return ret;
}
struct LibolmSessionCreationResult {
std::vector<uint8_t> outbound_data;
OlmOutboundGroupSession *outbound;
std::vector<uint8_t> inbound_data;
OlmInboundGroupSession *inbound;
};
LibolmSessionCreationResult create_libolm_session() {
LibolmSessionCreationResult res{
std::vector<uint8_t>(olm_outbound_group_session_size()),
0,
std::vector<uint8_t>(olm_inbound_group_session_size()),
0,
};
res.outbound = olm_outbound_group_session(res.outbound_data.data());
auto random = gen_random(olm_init_outbound_group_session_random_length(res.outbound));
check_olm_error(olm_init_outbound_group_session(res.outbound, random.data(), random.size()));
auto session_key = std::vector<uint8_t>(olm_outbound_group_session_key_length(res.outbound));
check_olm_error(olm_outbound_group_session_key(res.outbound, session_key.data(), session_key.size()));
res.inbound = olm_inbound_group_session(res.inbound_data.data());
olm_init_inbound_group_session(res.inbound, session_key.data(), session_key.size());
return res;
}
void require_decrypt_to(
Box<megolm::InboundGroupSession> &sess,
const Box<megolm::MegolmMessage> &msg,
std::string expected_plain) {
auto decrypted = REQUIRE_VODOZEMAC_OK(sess->MAYBE_NOEXCEPT(decrypt)(*msg));
REQUIRE(std::string(decrypted.plaintext.begin(), decrypted.plaintext.end()) == expected_plain);
}
TEST_CASE("Creation", "[GroupSessionTest]") {
auto [outbound, inbound] = create_session();
auto outbound_id = outbound->session_id();
auto inbound_id = inbound->session_id();
REQUIRE(outbound_id.length() != 0);
REQUIRE(outbound_id == inbound_id);
}
TEST_CASE("MessageIndex", "[GroupSessionTest]") {
auto [outbound, inbound] = create_session();
REQUIRE(outbound->message_index() == 0);
REQUIRE(inbound->first_known_index() == 0);
outbound->encrypt("Hello");
auto inbound2 = megolm::new_inbound_group_session(*outbound->session_key());
REQUIRE(outbound->message_index() == 1);
REQUIRE(inbound2->first_known_index() == 1);
}
TEST_CASE("merging", "[GroupSessionTest]") {
auto r = create_session();
auto outbound = std::move(r.outbound);
auto initial_inbound = std::move(r.inbound);
auto encrypted_msg = outbound->encrypt("{}");
auto current_key = outbound->session_key();
auto encrypted_msg2 = outbound->encrypt(R"({"a":"b"})");
SECTION("merging the same session at different index") {
auto current_inbound = megolm::new_inbound_group_session(*current_key);
auto merge_res = REQUIRE_VODOZEMAC_OK(current_inbound->MAYBE_NOEXCEPT(merge)(*initial_inbound));
require_decrypt_to(merge_res, encrypted_msg, "{}");
require_decrypt_to(merge_res, encrypted_msg2, R"({"a":"b"})");
}
SECTION("merging a session with itself") {
auto current_inbound = megolm::new_inbound_group_session(*current_key);
auto current_inbound2 = megolm::new_inbound_group_session(*current_key);
auto merge_res = REQUIRE_VODOZEMAC_OK(current_inbound->MAYBE_NOEXCEPT(merge)(*current_inbound2));
require_decrypt_to(merge_res, encrypted_msg2, R"({"a":"b"})");
REQUIRE_VODOZEMAC_ERROR(merge_res->MAYBE_NOEXCEPT(decrypt)(*encrypted_msg));
}
SECTION("refuse to merge different sessions") {
auto diff_session = megolm::new_group_session();
auto diff_key = diff_session->session_key();
auto diff_inbound = megolm::new_inbound_group_session(*diff_key);
REQUIRE_VODOZEMAC_ERROR(initial_inbound->MAYBE_NOEXCEPT(merge)(*diff_inbound));
}
}
TEST_CASE("Pickle", "[GroupSessionTest]") {
auto session = megolm::new_group_session();
auto pickle = session->pickle(PICKLE_KEY);
auto unpickled = REQUIRE_VODOZEMAC_OK(MAYBE_NOEXCEPT(megolm::group_session_from_pickle)(pickle, PICKLE_KEY));
REQUIRE(session->session_id() == unpickled->session_id());
REQUIRE(session->message_index() == unpickled->message_index());
}
TEST_CASE("PickleLibolm", "[GroupSessionTest]") {
auto [_1, outbound, _2, inbound] = create_libolm_session();
auto pickle = std::string(olm_pickle_outbound_group_session_length(outbound), '\0');
check_olm_error(olm_pickle_outbound_group_session(outbound, OLM_PICKLE_KEY.data(), OLM_PICKLE_KEY.size(), pickle.data(), pickle.size()));
auto unpickled = REQUIRE_VODOZEMAC_OK(
MAYBE_NOEXCEPT(megolm::group_session_from_libolm_pickle)
(String(pickle), Slice<const unsigned char>(OLM_PICKLE_KEY.data(), OLM_PICKLE_KEY.size())));
auto session_id = std::vector<uint8_t>(olm_outbound_group_session_id_length(outbound));
check_olm_error(olm_outbound_group_session_id(outbound, session_id.data(), session_id.size()));
REQUIRE(as_std_string(session_id) == as_std_string(unpickled->session_id()));
auto message_index = olm_outbound_group_session_message_index(outbound);
REQUIRE(message_index == unpickled->message_index());
}
TEST_CASE("PickleInbound", "[GroupSessionTest]") {
auto [outbound, inbound] = create_session();
auto pickle = inbound->pickle(PICKLE_KEY);
auto unpickled = REQUIRE_VODOZEMAC_OK(
MAYBE_NOEXCEPT(megolm::inbound_group_session_from_pickle)
(pickle, PICKLE_KEY));
REQUIRE(inbound->session_id() == unpickled->session_id());
REQUIRE(inbound->first_known_index() == unpickled->first_known_index());
}
TEST_CASE("PickleInboundLibolm", "[GroupSessionTest]") {
auto [_1, outbound, _2, inbound] = create_libolm_session();
auto pickle = std::string(olm_pickle_inbound_group_session_length(inbound), '\0');
check_olm_error(olm_pickle_inbound_group_session(inbound, OLM_PICKLE_KEY.data(), OLM_PICKLE_KEY.size(), pickle.data(), pickle.size()));
auto unpickled = REQUIRE_VODOZEMAC_OK(
MAYBE_NOEXCEPT(megolm::inbound_group_session_from_libolm_pickle)(pickle, Slice<const unsigned char>(OLM_PICKLE_KEY.data(), OLM_PICKLE_KEY.size())));
auto session_id = std::vector<uint8_t>(olm_inbound_group_session_id_length(inbound));
check_olm_error(olm_inbound_group_session_id(inbound, session_id.data(), session_id.size()));
REQUIRE(as_std_string(session_id) == static_cast<std::string>(unpickled->session_id()));
auto first_known_index = olm_inbound_group_session_first_known_index(inbound);
REQUIRE(first_known_index == unpickled->first_known_index());
}
TEST_CASE("UnpicklingFail", "[GroupSessionTest]") {
REQUIRE_VODOZEMAC_ERROR(MAYBE_NOEXCEPT(megolm::group_session_from_pickle)("", PICKLE_KEY));
REQUIRE_VODOZEMAC_ERROR(MAYBE_NOEXCEPT(megolm::inbound_group_session_from_pickle)("", PICKLE_KEY));
}
TEST_CASE("DecryptionFail", "[GroupSessionTest]") {
auto res = create_session();
// Because capturing structural bindings are c++20 and later,
// we write it as such here
auto &inbound = res.inbound;
auto outbound2 = megolm::new_group_session();
auto message = outbound2->encrypt("Hello");
REQUIRE_VODOZEMAC_ERROR(inbound->MAYBE_NOEXCEPT(decrypt)(*message));
}
TEST_CASE("Encryption", "[GroupSessionTest]") {
auto res = create_session();
// Because capturing structural bindings are c++20 and later,
// we write it as such here
auto &outbound = res.outbound;
auto &inbound = res.inbound;
auto plaintext = "It's a secret to everybody";
auto message = outbound->encrypt(plaintext);
auto decrypted = REQUIRE_VODOZEMAC_OK(inbound->MAYBE_NOEXCEPT(decrypt)(*message));
REQUIRE(as_std_string(decrypted.plaintext) == as_std_string(plaintext));
REQUIRE(decrypted.message_index == 0);
plaintext = "Another secret";
message = outbound->encrypt(plaintext);
decrypted = REQUIRE_VODOZEMAC_OK(inbound->MAYBE_NOEXCEPT(decrypt)(*message));
REQUIRE(as_std_string(decrypted.plaintext) == std::string(plaintext));
REQUIRE(decrypted.message_index == 1);
}
TEST_CASE("SessionExport", "[GroupSessionTest]") {
auto res = create_session();
// Because capturing structural bindings are c++20 and later,
// we write it as such here
auto &outbound = res.outbound;
auto &inbound = res.inbound;
auto exported = REQUIRE_VODOZEMAC_OK(inbound->MAYBE_NOEXCEPT(export_at)(0));
auto imported = megolm::import_inbound_group_session(*exported);
REQUIRE(outbound->session_id() == imported->session_id());
auto plaintext = "It's a secret to everybody";
auto message = outbound->encrypt(plaintext);
auto decrypted = REQUIRE_VODOZEMAC_OK(imported->MAYBE_NOEXCEPT(decrypt)(*message));
REQUIRE(as_std_string(decrypted.plaintext) == as_std_string(plaintext));
REQUIRE(decrypted.message_index == 0);
plaintext = "Another secret";
message = outbound->encrypt(plaintext);
decrypted = REQUIRE_VODOZEMAC_OK(imported->MAYBE_NOEXCEPT(decrypt)(*message));
REQUIRE(as_std_string(decrypted.plaintext) == as_std_string(plaintext));
REQUIRE(decrypted.message_index == 1);
}
diff --git a/cpp/tests/sas.cpp b/cpp/tests/sas.cpp
index c7f26f0..3d716ba 100644
--- a/cpp/tests/sas.cpp
+++ b/cpp/tests/sas.cpp
@@ -1,64 +1,64 @@
-#include "../../target/cxxbridge/vodozemac/src/lib.rs.h"
+#include <vodozemac.h>
#include <catch2/catch_test_macros.hpp>
#include "util.hpp"
using namespace rust;
using namespace vodozemac;
TEST_CASE("Creation", "[SasTest]") {
auto alice = sas::new_sas();
auto bob = sas::new_sas();
auto alice_key = alice->public_key()->to_base64();
auto bob_key = bob->public_key()->to_base64();
REQUIRE(alice_key != bob_key);
}
TEST_CASE("SharedSecret", "[SasTest]") {
auto alice = sas::new_sas();
auto bob = sas::new_sas();
auto alice_key = alice->public_key();
auto bob_key = bob->public_key();
auto alice_established = REQUIRE_VODOZEMAC_OK(alice->MAYBE_NOEXCEPT(diffie_hellman)(*bob_key));
auto bob_established = REQUIRE_VODOZEMAC_OK(bob->MAYBE_NOEXCEPT(diffie_hellman)(*alice_key));
}
TEST_CASE("ShortAuthString", "[SasTest]") {
auto alice = sas::new_sas();
auto bob = sas::new_sas();
auto alice_key = alice->public_key();
auto bob_key = bob->public_key();
auto alice_established = REQUIRE_VODOZEMAC_OK(alice->MAYBE_NOEXCEPT(diffie_hellman)(*bob_key));
auto bob_established = REQUIRE_VODOZEMAC_OK(bob->MAYBE_NOEXCEPT(diffie_hellman)(*alice_key));
auto alice_bytes = alice_established->bytes("");
auto bob_bytes = bob_established->bytes("");
REQUIRE(alice_bytes->emoji_indices() == bob_bytes->emoji_indices());
REQUIRE(alice_bytes->decimals() == bob_bytes->decimals());
}
TEST_CASE("CalculateMac", "[SasTest]") {
auto alice = sas::new_sas();
auto bob = sas::new_sas();
auto alice_key = alice->public_key();
auto bob_key = bob->public_key();
auto alice_established = REQUIRE_VODOZEMAC_OK(alice->MAYBE_NOEXCEPT(diffie_hellman)(*bob_key));
auto bob_established = REQUIRE_VODOZEMAC_OK(bob->MAYBE_NOEXCEPT(diffie_hellman)(*alice_key));
auto alice_mac = alice_established->calculate_mac("Hello", "world");
auto bob_mac = bob_established->calculate_mac("Hello", "world");
REQUIRE(alice_mac->to_base64() == bob_mac->to_base64());
REQUIRE_VODOZEMAC_OK(alice_established->MAYBE_NOEXCEPT(verify_mac)("Hello", "world", *bob_mac));
REQUIRE_VODOZEMAC_OK(bob_established->MAYBE_NOEXCEPT(verify_mac)("Hello", "world", *alice_mac));
REQUIRE_VODOZEMAC_ERROR(bob_established->MAYBE_NOEXCEPT(verify_mac)("", "", *alice_mac));
}
diff --git a/cpp/tests/session.cpp b/cpp/tests/session.cpp
index 8b3e896..ca7121f 100644
--- a/cpp/tests/session.cpp
+++ b/cpp/tests/session.cpp
@@ -1,198 +1,198 @@
-#include "../../target/cxxbridge/vodozemac/src/lib.rs.h"
+#include <vodozemac.h>
#include <catch2/catch_test_macros.hpp>
#include <boost/json.hpp>
#include "util.hpp"
using namespace rust;
using namespace vodozemac;
struct SessionCreationResult {
Box<olm::Account> alice;
Box<olm::Account> bob;
Box<olm::Session> session;
};
SessionCreationResult create_session() {
Box<olm::Account> alice = olm::new_account();
auto bob = olm::new_account();
bob->generate_one_time_keys(1);
auto one_time_keys = bob->one_time_keys();
auto [key_id, one_time_key] = std::move(one_time_keys.front());
auto identity_key = bob->curve25519_key();
auto session_config = olm::new_session_config_version_1();
auto session = REQUIRE_VODOZEMAC_OK(alice->MAYBE_NOEXCEPT(create_outbound_session)(*session_config, *identity_key, *one_time_key));
auto ret = SessionCreationResult{
std::move(alice),
std::move(bob),
std::move(session),
};
return ret;
}
TEST_CASE("Creation", "[SessionTest]") {
auto [alice, bob, session] = create_session();
auto session_id = session->session_id();
REQUIRE(session_id.length() != 0);
}
TEST_CASE("IdUniqueness", "[SessionTest]") {
auto [alice1, bob1, session] = create_session();
auto [alice2, bob2, session2] = create_session();
auto session_id = session->session_id();
auto session2_id = session2->session_id();
REQUIRE(session_id != session2_id);
}
TEST_CASE("Pickle", "[SessionTest]") {
auto [alice, bob, session] = create_session();
auto pickle = session->pickle(PICKLE_KEY);
auto unpickled = REQUIRE_VODOZEMAC_OK(MAYBE_NOEXCEPT(olm::session_from_pickle)(pickle, PICKLE_KEY));
auto session_id = session->session_id();
auto session2_id = unpickled->session_id();
REQUIRE(session_id == session2_id);
}
TEST_CASE("PickleFromLibolm", "[SessionTest]") {
auto [_1, alice] = new_olm_account();
auto [_2, bob] = new_olm_account();
auto random = gen_random(olm_account_generate_one_time_keys_random_length(bob, 1));
check_olm_error(olm_account_generate_one_time_keys(bob, 1, random.data(), random.size()));
auto one_time_keys = std::string(olm_account_one_time_keys_length(bob), '\0');
check_olm_error(olm_account_one_time_keys(bob, one_time_keys.data(), one_time_keys.size()));
auto parsed_keys = boost::json::parse(one_time_keys).as_object().at("curve25519").as_object();
auto key_id = as_std_string(parsed_keys.begin()->key());
auto one_time_key = as_std_string(parsed_keys.begin()->value().as_string());
auto identity_keys = std::string(olm_account_identity_keys_length(alice), '\0');
check_olm_error(olm_account_identity_keys(alice, identity_keys.data(), identity_keys.size()));
parsed_keys = boost::json::parse(identity_keys).as_object();
auto identity_key = String(as_std_string(parsed_keys.at("curve25519").as_string()));
auto data = std::vector<uint8_t>(olm_session_size());
auto session = olm_session(data.data());
random = gen_random(olm_create_outbound_session_random_length(session));
check_olm_error(olm_create_outbound_session(session, alice, identity_key.data(), identity_key.size(), one_time_key.data(), one_time_key.size(), random.data(), random.size()));
auto pickle = std::string(olm_pickle_session_length(session), '\0');
check_olm_error(olm_pickle_session(session, OLM_PICKLE_KEY.data(), OLM_PICKLE_KEY.size(), pickle.data(), pickle.size()));
auto unpickled = olm::session_from_libolm_pickle(pickle, Slice<const unsigned char>(OLM_PICKLE_KEY.data(), OLM_PICKLE_KEY.size()));
auto session_id = std::string(olm_session_id_length(session), '\0');
check_olm_error(olm_session_id(session, session_id.data(), session_id.size()));
auto session2_id = unpickled->session_id();
REQUIRE(session_id == as_std_string(session2_id));
}
TEST_CASE("InvalidPickle", "[SessionTest]") {
REQUIRE_VODOZEMAC_ERROR(MAYBE_NOEXCEPT(olm::session_from_pickle)("", PICKLE_KEY));
}
TEST_CASE("Encryption", "[SessionTest]") {
auto [alice, bob, session] = create_session();
auto alice_key = alice->curve25519_key();
auto plaintext = "It's a secret to everybody";
auto message = REQUIRE_VODOZEMAC_OK(session->MAYBE_NOEXCEPT(encrypt)(plaintext));
auto expected_config = olm::new_session_config_version_1();
auto [bob_session, decrypted] =
REQUIRE_VODOZEMAC_OK(bob->MAYBE_NOEXCEPT(create_inbound_session)(*expected_config, *alice_key, *message));
REQUIRE(session->session_id() ==
bob_session->session_id());
REQUIRE(std::string(plaintext) == as_std_string(decrypted));
}
TEST_CASE("InvalidDecryption", "[SessionTest]") {
auto parts = olm::OlmMessageParts{
0,
rust::Vec<std::uint8_t>(),
};
REQUIRE_VODOZEMAC_ERROR(MAYBE_NOEXCEPT(olm::olm_message_from_parts)(parts));
}
TEST_CASE("MultipleMessageDecryption", "[SessionTest]") {
auto [alice, bob, session] = create_session();
auto alice_key = alice->curve25519_key();
auto plaintext = "It's a secret to everybody";
auto message = REQUIRE_VODOZEMAC_OK(session->MAYBE_NOEXCEPT(encrypt)(plaintext));
auto expected_config = olm::new_session_config_version_1();
auto [bob_session, decrypted] =
REQUIRE_VODOZEMAC_OK(bob->MAYBE_NOEXCEPT(create_inbound_session)(*expected_config, *alice_key, *message));
REQUIRE(session->session_id() ==
bob_session->session_id());
REQUIRE(std::string(plaintext) == as_std_string(decrypted));
plaintext = "Grumble grumble";
message = REQUIRE_VODOZEMAC_OK(bob_session->MAYBE_NOEXCEPT(encrypt)(plaintext));
decrypted = REQUIRE_VODOZEMAC_OK(session->MAYBE_NOEXCEPT(decrypt)(*message));
REQUIRE(std::string(plaintext) == as_std_string(decrypted));
}
TEST_CASE("PreKeyMatches", "[SessionTest]") {
auto [alice, bob, session] = create_session();
auto alice_key = alice->curve25519_key();
auto plaintext = "It's a secret to everybody";
auto message = REQUIRE_VODOZEMAC_OK(session->MAYBE_NOEXCEPT(encrypt)(plaintext));
auto expected_config = olm::new_session_config_version_1();
auto [bob_session, decrypted] =
REQUIRE_VODOZEMAC_OK(bob->MAYBE_NOEXCEPT(create_inbound_session)(*expected_config, *alice_key, *message));
plaintext = "Grumble grumble";
message = REQUIRE_VODOZEMAC_OK(session->MAYBE_NOEXCEPT(encrypt)(plaintext));
REQUIRE(bob_session->session_matches(*message));
}
TEST_CASE("PreKeyDoesNotMatch", "[SessionTest]") {
auto [alice, bob, session] = create_session();
auto [alice2, bob2, session2] = create_session();
auto alice_key = alice->curve25519_key();
auto plaintext = "It's a secret to everybody";
auto message = REQUIRE_VODOZEMAC_OK(session->MAYBE_NOEXCEPT(encrypt)(plaintext));
auto expected_config = olm::new_session_config_version_1();
auto [bob_session, decrypted] =
REQUIRE_VODOZEMAC_OK(bob->MAYBE_NOEXCEPT(create_inbound_session)(*expected_config, *alice_key, *message));
plaintext = "Grumble grumble";
message = session2->encrypt(plaintext);
REQUIRE_FALSE(bob_session->session_matches(*message));
}
TEST_CASE("InvalidOneTimeKey", "[SessionTest]") {
REQUIRE_VODOZEMAC_ERROR(MAYBE_NOEXCEPT(types::curve_key_from_base64)(""));
}
diff --git a/cpp/tests/util.hpp b/cpp/tests/util.hpp
index 97cc257..f6d415d 100644
--- a/cpp/tests/util.hpp
+++ b/cpp/tests/util.hpp
@@ -1,102 +1,102 @@
#pragma once
#include <random>
#include <algorithm>
#include <optional>
#include <array>
#include <vector>
#include <functional>
#include <catch2/catch_test_macros.hpp>
#include <olm/olm.h>
-#include "../../target/cxxbridge/vodozemac/src/lib.rs.h"
+#include <vodozemac.h>
inline std::array<uint8_t, 32> PICKLE_KEY = {};
// olm pickles are of variable length and are then hashed to obtain the actual key
inline std::vector<uint8_t> OLM_PICKLE_KEY = {0, 7, 2, 1};
[[nodiscard]] inline std::vector<uint8_t> gen_random(int len)
{
auto rd = std::random_device{};
auto ret = std::vector<uint8_t>(len, '\0');
std::generate(ret.begin(), ret.end(), [&] { return rd(); });
return ret;
}
[[nodiscard]] inline rust::Slice<const std::uint8_t> as_u8_slice(const std::string &str)
{
return rust::Slice<const std::uint8_t>(reinterpret_cast<const std::uint8_t *>(str.data()), str.size());
}
inline void check_olm_error(std::size_t code)
{
REQUIRE(code != olm_error());
}
template<class T>
[[nodiscard]] inline std::string as_std_string(const T &range)
{
return std::string(range.begin(), range.end());
}
[[nodiscard]] inline std::string as_std_string(const char *cStr)
{
return std::string(cStr);
}
std::pair<std::vector<uint8_t>, OlmAccount *> new_olm_account()
{
auto data = std::vector<uint8_t>(olm_account_size());
auto account = olm_account(data.data());
auto random = gen_random(olm_create_account_random_length(account));
check_olm_error(olm_create_account(account, random.data(), random.size()));
return {std::move(data), account};
}
#if VODOZEMAC_TEST_EXCEPTIONS
#define MAYBE_NOEXCEPT(funcName) funcName
template<class Func>
inline auto require_vodozemac_ok(Func &&f)
{
try {
return std::invoke(std::forward<Func>(f));
} catch (const std::exception &e) {
REQUIRE_NOTHROW(throw e);
// the following line is unreachable
std::abort();
}
}
template<class Func>
inline std::string require_vodozemac_error(Func &&f)
{
try {
std::invoke(std::forward<Func>(f));
} catch (const std::exception &e) {
return e.what();
}
FAIL("expects an exception");
return "";
}
#else
#define MAYBE_NOEXCEPT(funcName) funcName##_noexcept
template<class Func>
inline auto require_vodozemac_ok(Func &&f)
{
auto res = std::invoke(std::forward<Func>(f));
REQUIRE(res->has_value());
return res->take_value();
}
template<class Func>
inline std::string require_vodozemac_error(Func &&f)
{
auto res = std::invoke(std::forward<Func>(f));
REQUIRE(!res->has_value());
auto error = res->take_error();
return as_std_string(error);
}
#endif
#define REQUIRE_VODOZEMAC_OK(...) require_vodozemac_ok([&] { return __VA_ARGS__; })
#define REQUIRE_VODOZEMAC_ERROR(...) require_vodozemac_error([&] { return __VA_ARGS__; })

File Metadata

Mime Type
text/x-diff
Expires
Sat, Oct 31, 4:36 AM (17 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1801030
Default Alt Text
(41 KB)

Event Timeline