Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85828247
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
41 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Oct 31, 4:32 AM (17 h, 23 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1801030
Default Alt Text
(41 KB)
Attached To
Mode
rVB vodozemac-bindings
Attached
Detach File
Event Timeline