From 578065be477b5c17c89e437ba7c000b6a3d1fbfd Mon Sep 17 00:00:00 2001 From: Kurt Sassenrath Date: Mon, 6 Nov 2023 16:16:04 -0800 Subject: [PATCH] More session id work --- include/parselink/proto/session_id.h | 30 +++++++++++++--- source/proto/BUILD | 1 + source/proto/session_id.cpp | 38 ++++++++++++++++++++ tests/proto/BUILD | 22 ++++++++++++ tests/proto/test_main.cpp | 2 ++ tests/proto/test_session_id.cpp | 52 ++++++++++++++++++++++++++++ 6 files changed, 141 insertions(+), 4 deletions(-) create mode 100644 source/proto/session_id.cpp create mode 100644 tests/proto/BUILD create mode 100644 tests/proto/test_main.cpp create mode 100644 tests/proto/test_session_id.cpp diff --git a/include/parselink/proto/session_id.h b/include/parselink/proto/session_id.h index c6e7828..45ee1d0 100644 --- a/include/parselink/proto/session_id.h +++ b/include/parselink/proto/session_id.h @@ -27,20 +27,42 @@ namespace parselink { namespace proto { struct session_id { - std::array bytes; +public: session_id() noexcept; + // Not the intended way to build a session id. Ideally, they'll be randomly + // generated. + explicit constexpr session_id(std::array const& v) noexcept { + std::copy(v.begin(), v.end(), bytes_.begin()); + } + [[nodiscard]] constexpr auto operator<=>( session_id const& other) const noexcept { - return bytes <=> other.bytes; + return bytes_ <=> other.bytes_; + } + + [[nodiscard]] constexpr auto operator==( + session_id const& other) const noexcept { + return bytes_ == other.bytes_; } [[nodiscard]] constexpr auto operator<=>( std::span other) const noexcept { - return std::lexicographical_compare_three_way(bytes.begin(), - bytes.end(), other.begin(), other.end(), + return std::lexicographical_compare_three_way(bytes_.begin(), + bytes_.end(), other.begin(), other.end(), std::compare_three_way()); } + + [[nodiscard]] constexpr auto operator==( + std::span other) const noexcept { + return std::equal(bytes_.begin(), bytes_.end(), other.begin(), other.end()); + } + + constexpr std::span raw() const noexcept { + return bytes_; + } +private: + std::array bytes_; }; } // namespace proto diff --git a/source/proto/BUILD b/source/proto/BUILD index 7301a79..c42d012 100644 --- a/source/proto/BUILD +++ b/source/proto/BUILD @@ -4,6 +4,7 @@ cc_library( name = "proto", srcs = [ "session.cpp", + "session_id.cpp", ], deps = [ "//include/parselink:proto", diff --git a/source/proto/session_id.cpp b/source/proto/session_id.cpp new file mode 100644 index 0000000..fe99655 --- /dev/null +++ b/source/proto/session_id.cpp @@ -0,0 +1,38 @@ +//----------------------------------------------------------------------------- +// ___ __ _ _ +// / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __ +// / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ / +// / ___/ (_| | | \__ \ __/ /__| | | | | < +// \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ . +// +//----------------------------------------------------------------------------- +// Author: Kurt Sassenrath +// Module: proto +// +// Session ID implementation +// +// Copyright (c) 2023 Kurt Sassenrath. +// +// License TBD. +//----------------------------------------------------------------------------- +#include "parselink/proto/session_id.h" + +#include "hydrogen.h" + +namespace { +void ensure_initialized() { + static auto init_crng [[maybe_unused]] = [] { return hydro_init(); }(); +} + +template +auto get_random_bytes() { + ensure_initialized(); + std::array out; + hydro_random_buf(out.data(), N); + return out; +} + +} + +using namespace parselink::proto; +session_id::session_id() noexcept : bytes_(get_random_bytes<32>()) {} diff --git a/tests/proto/BUILD b/tests/proto/BUILD new file mode 100644 index 0000000..6526af4 --- /dev/null +++ b/tests/proto/BUILD @@ -0,0 +1,22 @@ + +cc_library( + name = "test_deps", + srcs = [ + "test_main.cpp", + ], + deps = [ + "//source/proto", + "@expected", + "@fmt", + "@magic_enum", + "@ut", + ], +) + +cc_test( + name = "session_id", + srcs = [ + "test_session_id.cpp", + ], + deps = ["test_deps"], +) diff --git a/tests/proto/test_main.cpp b/tests/proto/test_main.cpp new file mode 100644 index 0000000..2abeaa7 --- /dev/null +++ b/tests/proto/test_main.cpp @@ -0,0 +1,2 @@ + +int main(int, char**) {} diff --git a/tests/proto/test_session_id.cpp b/tests/proto/test_session_id.cpp new file mode 100644 index 0000000..a1122f8 --- /dev/null +++ b/tests/proto/test_session_id.cpp @@ -0,0 +1,52 @@ +#include +#include + +#include + +namespace { + +using namespace boost::ut; +using namespace parselink::proto; + +template +constexpr std::array make_bytes(Bytes&&... bytes) { + return {std::byte(std::forward(bytes))...}; +} + +constexpr std::array null_id_bytes = {}; + +} + +suite session_id_tests = [] { + "test explicitly generated session ids"_test = [] { + constexpr session_id sid1(null_id_bytes); + constexpr session_id sid2(null_id_bytes); + expect(sid1 == sid2); + expect(sid1 == null_id_bytes); + constexpr auto basic_id = make_bytes( + 0x0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f); + constexpr session_id sid3(basic_id); + constexpr session_id sid4(basic_id); + expect(sid3 == sid4); + expect(sid3 == basic_id); + }; + + "test random generated"_test = [] { + session_id sid1; + session_id sid2; + expect(sid1 != null_id_bytes); + expect(sid2 != null_id_bytes); + expect(sid1 != sid2); + }; + + "test random generated entropy"_test = [] { + constexpr static std::size_t iter_count = 100000; + std::set sessions; + while (sessions.size() < iter_count) { + session_id s; + expect(!sessions.contains(s)); + sessions.insert(std::move(s)); + } + }; +};