// Copyright 2025 Steven Le Rouzic // // SPDX-License-Identifier: BSD-3-Clause #include "asl/testing/testing.hpp" #include "asl/hashing/hash.hpp" #include "asl/strings/string_view.hpp" #include "asl/strings/string.hpp" #include "asl/containers/buffer.hpp" #include "asl/types/box.hpp" #include "asl/types/option.hpp" #include "asl/types/status.hpp" #include "asl/types/status_or.hpp" static_assert(!asl::hashable); static_assert(!asl::hashable); static_assert(!asl::hashable); static_assert(asl::hashable); static_assert(asl::hashable); static_assert(asl::hashable); static_assert(asl::hashable); static_assert(asl::hashable); static_assert(asl::hashable); static_assert(asl::hashable); static_assert(asl::hashable); static_assert(asl::hashable); ASL_TEST(integers) { const uint64_t a = asl::hash_value(45); const uint64_t b = asl::hash_value(45); const uint64_t c = asl::hash_value(46); const uint64_t d = asl::hash_value(45); ASL_TEST_EXPECT(a == b); ASL_TEST_EXPECT(a != c); ASL_TEST_EXPECT(a != d); } static_assert(asl::hashable); ASL_TEST(bool) { ASL_TEST_EXPECT(asl::hash_value(true) == asl::hash_value(true)); ASL_TEST_EXPECT(asl::hash_value(false) == asl::hash_value(false)); ASL_TEST_EXPECT(asl::hash_value(true) != asl::hash_value(false)); } static_assert(asl::hashable); static_assert(asl::hashable>); ASL_TEST(strings) { ASL_TEST_EXPECT(asl::hash_value("hello"_sv) == asl::hash_value("hello"_sv)); ASL_TEST_EXPECT(asl::hash_value("hello"_sv) != asl::hash_value("hello "_sv)); ASL_TEST_EXPECT(asl::hash_value("hello"_sv) != asl::hash_value("HELLO"_sv)); ASL_TEST_EXPECT(asl::hash_value(asl::string("hello"_sv)) == asl::hash_value(asl::string("hello"_sv))); ASL_TEST_EXPECT(asl::hash_value(asl::string("hello"_sv)) != asl::hash_value(asl::string("hello "_sv))); ASL_TEST_EXPECT(asl::hash_value(asl::string("hello"_sv)) != asl::hash_value(asl::string("HELLO"_sv))); ASL_TEST_EXPECT(asl::hash_value("hello"_sv) == asl::hash_value(asl::string("hello"_sv))); } static_assert(asl::hashable>); static_assert(!asl::hashable>); static_assert(asl::hashable>); ASL_TEST(span) { int ints1[] = {1, 2, 3}; int ints2[] = {1, 2, 3}; int ints3[] = {1, 2}; int ints4[] = {3, 2, 1}; ASL_TEST_EXPECT(asl::hash_value(asl::span(ints1)) == asl::hash_value(asl::span(ints2))); ASL_TEST_EXPECT(asl::hash_value(asl::span(ints1)) != asl::hash_value(asl::span(ints3))); ASL_TEST_EXPECT(asl::hash_value(asl::span(ints1)) != asl::hash_value(asl::span(ints4))); asl::string_view strs1[] = {"a", "abc", "hello"}; asl::string_view strs2[] = {"a", "abc", "hello"}; asl::string_view strs3[] = {"a", "abc"}; asl::string_view strs4[] = {"a", "abc", "hello", "what"}; ASL_TEST_EXPECT(asl::hash_value(asl::span(strs1)) == asl::hash_value(asl::span(strs2))); ASL_TEST_EXPECT(asl::hash_value(asl::span(strs1)) != asl::hash_value(asl::span(strs3))); ASL_TEST_EXPECT(asl::hash_value(asl::span(strs1)) != asl::hash_value(asl::span(strs4))); } static_assert(asl::hashable>); static_assert(!asl::hashable>); ASL_TEST(buffer) { asl::buffer ints1; ints1.push(1); ints1.push(2); ints1.push(3); asl::buffer ints2; ints2.push(1); ints2.push(2); ints2.push(3); asl::buffer ints3; ints3.push(1); ints3.push(2); asl::buffer ints4; ints4.push(1); ints4.push(2); ints4.push(4); ASL_TEST_EXPECT(asl::hash_value(ints1) == asl::hash_value(ints2)); ASL_TEST_EXPECT(asl::hash_value(ints1) != asl::hash_value(ints3)); ASL_TEST_EXPECT(asl::hash_value(ints1) != asl::hash_value(ints4)); ASL_TEST_EXPECT(asl::hash_value(ints1) == asl::hash_value(ints1.as_span())); asl::buffer strs1; strs1.push("Hello"); strs1.push("World"); asl::buffer strs2; strs2.push("Hello"); strs2.push("World"); asl::buffer strs3; strs3.push("Hello"); strs3.push("world"); asl::buffer strs4; strs4.push("Hello"); strs4.push("World"); strs4.push("World"); ASL_TEST_EXPECT(asl::hash_value(strs1) == asl::hash_value(strs2)); ASL_TEST_EXPECT(asl::hash_value(strs1) != asl::hash_value(strs3)); ASL_TEST_EXPECT(asl::hash_value(strs1) != asl::hash_value(strs4)); ASL_TEST_EXPECT(asl::hash_value(strs1) == asl::hash_value(strs1.as_span())); } enum Enum1 {}; enum class Enum2 {}; static_assert(asl::hashable); static_assert(asl::hashable); static_assert(!asl::hashable>); static_assert(asl::hashable>); ASL_TEST(box) { auto b1 = asl::make_box("Hello, world!"); auto b2 = asl::make_box("Hello, world!"); auto b3 = asl::make_box("Hello, world! 2"); ASL_TEST_EXPECT(asl::hash_value(b1) == asl::hash_value(b2)); ASL_TEST_EXPECT(asl::hash_value(b1) != asl::hash_value(b3)); ASL_TEST_EXPECT(asl::hash_value(b1) == asl::hash_value("Hello, world!"_sv)); } struct NonZero { int value; constexpr explicit NonZero(int x) : value(x) { ASL_ASSERT(x != 0); } constexpr explicit NonZero(asl::niche_t) : value(0) {} constexpr bool operator==(asl::niche_t) const { return value == 0; } }; namespace asl { template<> struct is_uniquely_represented : true_type {}; } static_assert(asl::has_niche); static_assert(asl::uniquely_represented); static_assert(asl::hashable>); static_assert(!asl::hashable>); static_assert(asl::hashable>); static_assert(asl::hashable>); static_assert(asl::uniquely_represented>); ASL_TEST(option) { const asl::option int1 = 0; const asl::option int2 = 0; const asl::option int3 = 1; const asl::option int4 = asl::nullopt; ASL_TEST_EXPECT(asl::hash_value(int1) == asl::hash_value(int2)); ASL_TEST_EXPECT(asl::hash_value(int1) != asl::hash_value(int3)); ASL_TEST_EXPECT(asl::hash_value(int1) != asl::hash_value(int4)); const asl::option noz1{8}; const asl::option noz2{8}; const asl::option noz3{9}; const asl::option noz4 = asl::nullopt; ASL_TEST_EXPECT(asl::hash_value(noz1) == asl::hash_value(noz2)); ASL_TEST_EXPECT(asl::hash_value(noz1) != asl::hash_value(noz3)); ASL_TEST_EXPECT(asl::hash_value(noz1) != asl::hash_value(noz4)); } static_assert(asl::hashable); // NOLINTNEXTLINE(*-cognitive-complexity) ASL_TEST(status) { const asl::status s1 = asl::ok(); const asl::status s2 = asl::ok(); const asl::status s3 = asl::internal_error(); const asl::status s4 = asl::internal_error(); const asl::status s5 = asl::runtime_error(); const asl::status s6 = asl::internal_error("Oh, no!"); const asl::status s7 = asl::internal_error("Oh, no!"); const asl::status s8 = asl::internal_error("Oh, no"); const asl::status s9 = asl::runtime_error("Oh, no!"); ASL_TEST_EXPECT(asl::hash_value(s1) == asl::hash_value(s2)); ASL_TEST_EXPECT(asl::hash_value(s3) == asl::hash_value(s4)); ASL_TEST_EXPECT(asl::hash_value(s6) == asl::hash_value(s7)); ASL_TEST_EXPECT(asl::hash_value(s1) != asl::hash_value(s3)); ASL_TEST_EXPECT(asl::hash_value(s1) != asl::hash_value(s5)); ASL_TEST_EXPECT(asl::hash_value(s1) != asl::hash_value(s6)); ASL_TEST_EXPECT(asl::hash_value(s1) != asl::hash_value(s9)); ASL_TEST_EXPECT(asl::hash_value(s3) != asl::hash_value(s5)); ASL_TEST_EXPECT(asl::hash_value(s3) != asl::hash_value(s6)); ASL_TEST_EXPECT(asl::hash_value(s3) != asl::hash_value(s8)); ASL_TEST_EXPECT(asl::hash_value(s3) != asl::hash_value(s9)); ASL_TEST_EXPECT(asl::hash_value(s6) != asl::hash_value(s8)); ASL_TEST_EXPECT(asl::hash_value(s6) != asl::hash_value(s9)); } static_assert(asl::hashable>); static_assert(asl::hashable>); static_assert(!asl::hashable>); ASL_TEST(status_or) { const asl::status_or s1 = 42; const asl::status_or s2 = 42; const asl::status_or s3 = 43; const asl::status_or s4 = asl::runtime_error(); const asl::status_or s5 = asl::runtime_error(); const asl::status_or s6 = asl::runtime_error("Hello"); const asl::status_or s7 = asl::runtime_error("Hello"); ASL_TEST_EXPECT(asl::hash_value(s1) == asl::hash_value(s2)); ASL_TEST_EXPECT(asl::hash_value(s4) == asl::hash_value(s5)); ASL_TEST_EXPECT(asl::hash_value(s6) == asl::hash_value(s7)); ASL_TEST_EXPECT(asl::hash_value(s1) != asl::hash_value(s3)); ASL_TEST_EXPECT(asl::hash_value(s1) != asl::hash_value(s4)); ASL_TEST_EXPECT(asl::hash_value(s1) != asl::hash_value(s6)); ASL_TEST_EXPECT(asl::hash_value(s4) != asl::hash_value(s6)); }