diff options
Diffstat (limited to 'nearby/presence/np_cpp_ffi/tests/v1_public_identity_tests.cc')
-rw-r--r-- | nearby/presence/np_cpp_ffi/tests/v1_public_identity_tests.cc | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/nearby/presence/np_cpp_ffi/tests/v1_public_identity_tests.cc b/nearby/presence/np_cpp_ffi/tests/v1_public_identity_tests.cc new file mode 100644 index 0000000..aa32f7b --- /dev/null +++ b/nearby/presence/np_cpp_ffi/tests/v1_public_identity_tests.cc @@ -0,0 +1,232 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "nearby_protocol.h" +#include "shared_test_util.h" +#include "np_cpp_test.h" + +#include "gtest/gtest.h" + +TEST_F(NpCppTest, V1SimpleTestCase) { + auto maybe_credential_slab = nearby_protocol::CredentialSlab::TryCreate(); + ASSERT_TRUE(maybe_credential_slab.ok()); + auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(maybe_credential_slab.value()); + ASSERT_TRUE(maybe_credential_book.ok()); + + auto deserialize_result = + nearby_protocol::Deserializer::DeserializeAdvertisement( + V1AdvSimple, maybe_credential_book.value()); + ASSERT_EQ(deserialize_result.GetKind(), + nearby_protocol::DeserializeAdvertisementResultKind::V1); + + auto v1_adv = deserialize_result.IntoV1(); + ASSERT_EQ(v1_adv.GetNumLegibleSections(), 1); + ASSERT_EQ(v1_adv.GetNumUndecryptableSections(), 0); + + auto invalid = v1_adv.TryGetSection(1); + ASSERT_FALSE(invalid.ok()); + ASSERT_TRUE(absl::IsOutOfRange(invalid.status())); + + auto section = v1_adv.TryGetSection(0); + ASSERT_TRUE(section.ok()); + ASSERT_EQ(section.value().GetIdentityKind(), + nearby_protocol::DeserializedV1IdentityKind::Plaintext); + ASSERT_EQ(section.value().NumberOfDataElements(), 1); + + auto invalid_de = section.value().TryGetDataElement(1); + ASSERT_FALSE(invalid_de.ok()); + ASSERT_TRUE(absl::IsOutOfRange(invalid_de.status())); + + auto de = section.value().TryGetDataElement(0); + ASSERT_TRUE(de.ok()); + ASSERT_EQ(de.value().GetDataElementTypeCode(), (uint8_t)5); + + auto payload = de.value().GetPayload(); + auto vec = payload.ToVector(); + std::vector<uint8_t> expected{3}; + ASSERT_EQ(vec, expected); +} + +TEST_F(NpCppTest, TestV1AdvMoveConstructor) { + auto slab = nearby_protocol::CredentialSlab::TryCreate().value(); + auto book = nearby_protocol::CredentialBook::TryCreateFromSlab(slab).value(); + auto result = nearby_protocol::Deserializer::DeserializeAdvertisement( + V1AdvSimple, book); + ASSERT_EQ(result.GetKind(), + np_ffi::internal::DeserializeAdvertisementResultKind::V1); + auto adv = result.IntoV1(); + + // Now move the adv into a new value, and make sure its still valid + nearby_protocol::DeserializedV1Advertisement moved_adv(std::move(adv)); + ASSERT_EQ(moved_adv.GetNumLegibleSections(), 1); + + // trying to use the moved object should result in a use after free which + // triggers an abort + ASSERT_DEATH( + [[maybe_unused]] auto failure = + adv.GetNumLegibleSections(), // NOLINT(bugprone-use-after-move + ""); + ASSERT_DEATH( + [[maybe_unused]] auto failure = adv.GetNumUndecryptableSections(), ""); + ASSERT_DEATH([[maybe_unused]] auto failure = adv.TryGetSection(0), ""); + + // moving again should still preserve the moved state and also lead to an + // abort + nearby_protocol::DeserializedV1Advertisement moved_again(std::move(adv)); + ASSERT_DEATH( + [[maybe_unused]] auto failure = + moved_again.GetNumLegibleSections(), // NOLINT(bugprone-use-after-move + ""); + ASSERT_DEATH([[maybe_unused]] auto failure = + moved_again.GetNumUndecryptableSections(), + ""); + ASSERT_DEATH([[maybe_unused]] auto failure = moved_again.TryGetSection(0), + ""); +} + +TEST_F(NpCppTest, TestV1AdvMoveAssignment) { + auto slab = nearby_protocol::CredentialSlab::TryCreate().value(); + auto book = nearby_protocol::CredentialBook::TryCreateFromSlab(slab).value(); + auto result = nearby_protocol::Deserializer::DeserializeAdvertisement( + V1AdvSimple, book); + ASSERT_EQ(result.GetKind(), + np_ffi::internal::DeserializeAdvertisementResultKind::V1); + auto adv = result.IntoV1(); + + // create a second result + auto another_result = nearby_protocol::Deserializer::DeserializeAdvertisement( + V1AdvSimple, book); + ASSERT_EQ(another_result.GetKind(), + np_ffi::internal::DeserializeAdvertisementResultKind::V1); + auto adv2 = another_result.IntoV1(); + + // move adv2 into adv, the original should be deallocated by assignment + adv2 = std::move(adv); + ASSERT_EQ(adv2.GetNumLegibleSections(), 1); + + // original result should now be invalid, using it will trigger a use after + // free abort. + ASSERT_DEATH( + [[maybe_unused]] auto failure = + adv.GetNumLegibleSections(), // NOLINT(bugprone-use-after-move + ""); + ASSERT_DEATH( + [[maybe_unused]] auto failure = adv.GetNumUndecryptableSections(), ""); + ASSERT_DEATH([[maybe_unused]] auto failure = adv.TryGetSection(0), ""); + + // moving again should still lead to an error + auto moved_again = std::move(adv); + ASSERT_DEATH( + [[maybe_unused]] auto failure = + moved_again.GetNumLegibleSections(), // NOLINT(bugprone-use-after-move + ""); + ASSERT_DEATH([[maybe_unused]] auto failure = + moved_again.GetNumUndecryptableSections(), + ""); + ASSERT_DEATH([[maybe_unused]] auto failure = moved_again.TryGetSection(0), + ""); +} + +nearby_protocol::DeserializedV1Section +GetSection(nearby_protocol::CredentialBook &book) { + // Create the adv in this scope, so its de-allocated at the end of this call. + // The section should still be valid + auto v1_adv = + nearby_protocol::Deserializer::DeserializeAdvertisement(V1AdvSimple, book) + .IntoV1(); + auto section = v1_adv.TryGetSection(0); + return section.value(); +} + +bool TryDeserializeNewV1Adv(nearby_protocol::CredentialBook &book) { + auto adv = nearby_protocol::Deserializer::DeserializeAdvertisement( + V1AdvSimple, book); + return adv.GetKind() == + np_ffi::internal::DeserializeAdvertisementResultKind::V1; +} + +TEST_F(NpCppTest, TestSectionOwnership) { + auto maybe_credential_slab = nearby_protocol::CredentialSlab::TryCreate(); + ASSERT_TRUE(maybe_credential_slab.ok()); + auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreateFromSlab(maybe_credential_slab.value()); + ASSERT_TRUE(maybe_credential_book.ok()); + + { + auto section = GetSection(maybe_credential_book.value()); + ASSERT_EQ(section.GetIdentityKind(), + nearby_protocol::DeserializedV1IdentityKind::Plaintext); + ASSERT_EQ(section.NumberOfDataElements(), 1); + ASSERT_TRUE(section.TryGetDataElement(0).ok()); + + auto section2 = GetSection(maybe_credential_book.value()); + ASSERT_EQ(section2.GetIdentityKind(), + nearby_protocol::DeserializedV1IdentityKind::Plaintext); + ASSERT_EQ(section2.NumberOfDataElements(), 1); + ASSERT_TRUE(section2.TryGetDataElement(0).ok()); + + ASSERT_FALSE(TryDeserializeNewV1Adv(maybe_credential_book.value())); + } + + // now that the section has gone out of scope, deserializing a new adv should + // succeed + ASSERT_TRUE(TryDeserializeNewV1Adv(maybe_credential_book.value())); +} + +/* + * Multiple sections are not supported in plaintext advertisements + * TODO Update the below test to use encrypted sections +TEST(NpCppTest, V1MultipleSections) { + auto maybe_credential_book = nearby_protocol::CredentialBook::TryCreate(); + ASSERT_TRUE(maybe_credential_book.ok()); + + auto deserialize_result = + nearby_protocol::Deserializer::DeserializeAdvertisement( + V1AdvMultipleSections, maybe_credential_book.value()); + ASSERT_EQ(deserialize_result.GetKind(), + nearby_protocol::DeserializeAdvertisementResultKind::V1); + + auto v1_adv = deserialize_result.IntoV1(); + ASSERT_EQ(v1_adv.GetNumLegibleSections(), 2); + ASSERT_EQ(v1_adv.GetNumUndecryptableSections(), 0); + + auto invalid = v1_adv.TryGetSection(2); + ASSERT_FALSE(invalid.ok()); + ASSERT_TRUE(absl::IsOutOfRange(invalid.status())); + + auto section = v1_adv.TryGetSection(0); + ASSERT_TRUE(section.ok()); + ASSERT_EQ(section.value().GetIdentityKind(), + nearby_protocol::DeserializedV1IdentityKind::Plaintext); + ASSERT_EQ(section.value().NumberOfDataElements(), 1); + + auto invalid_de = section.value().TryGetDataElement(1); + ASSERT_FALSE(invalid_de.ok()); + ASSERT_TRUE(absl::IsOutOfRange(invalid_de.status())); + + auto de = section.value().TryGetDataElement(0); + ASSERT_TRUE(de.ok()); + ASSERT_EQ(de.value().GetDataElementTypeCode(), 6); + + auto payload = de.value().GetPayload(); + auto vec = payload.ToVector(); + std::vector<uint8_t> expected{0x00, 0x46}; + ASSERT_EQ(vec, expected); + + auto section2 = v1_adv.TryGetSection(1); + ASSERT_TRUE(section2.ok()); + ASSERT_EQ(section2.value().GetIdentityKind(), + nearby_protocol::DeserializedV1IdentityKind::Plaintext); + ASSERT_EQ(section2.value().NumberOfDataElements(), 1); +} +*/ |