diff --git a/internal/platform/BUILD b/internal/platform/BUILD index 87210560..a7ad448b 100644 --- a/internal/platform/BUILD +++ b/internal/platform/BUILD @@ -53,6 +53,7 @@ cc_library( "//internal/proto/analytics:__subpackages__", "//location/nearby/cpp/sharing:__subpackages__", "//third_party/nearby/cpp/cal:__subpackages__", + "//third_party/nearby/presence:__subpackages__", ], deps = [ "@com_google_absl//absl/container:flat_hash_map", diff --git a/presence/BUILD b/presence/BUILD index 8e5bbc14..4848e991 100644 --- a/presence/BUILD +++ b/presence/BUILD @@ -13,27 +13,51 @@ # limitations under the License. licenses(["notice"]) +cc_library( + name = "presence", + srcs = [ + "presence_client.cc", + ], + hdrs = [ + "presence_client.h", + ], + visibility = [ + "//third_party/nearby:__subpackages__", + ], + deps = [ + ":types", + ], +) + cc_library( name = "types", srcs = [ "device_motion.cc", "discovery_filter.cc", "presence_action.cc", + "presence_client.cc", + "presence_device.cc", "presence_identity.cc", "presence_zone.cc", ], hdrs = [ + "broadcast_options.h", "device_motion.h", "discovery_filter.h", "discovery_options.h", + "listeners.h", "presence_action.h", + "presence_client.h", + "presence_device.h", "presence_identity.h", "presence_zone.h", + "status.h", ], visibility = [ "//third_party/nearby/presence:__subpackages__", ], deps = [ + "//internal/platform:base", "@com_google_absl//absl/strings", "@com_google_absl//absl/types:variant", "@com_google_glog//:glog", @@ -44,12 +68,15 @@ cc_test( name = "types_test", size = "small", srcs = [ + "broadcast_options_test.cc", "device_motion_test.cc", "discovery_filter_test.cc", "discovery_options_test.cc", "presence_action_test.cc", + "presence_device_test.cc", "presence_identity_test.cc", "presence_zone_test.cc", + "status_test.cc", ], shard_count = 6, deps = [ @@ -58,3 +85,17 @@ cc_test( "@com_google_googletest//:gtest_main", ], ) + +cc_test( + name = "presence_test", + size = "small", + srcs = [ + "presence_client_test.cc", + ], + shard_count = 6, + deps = [ + ":presence", + "@com_github_protobuf_matchers//protobuf-matchers", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/presence/broadcast_options.h b/presence/broadcast_options.h new file mode 100644 index 00000000..18d11440 --- /dev/null +++ b/presence/broadcast_options.h @@ -0,0 +1,36 @@ +// Copyright 2020 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 +// +// https://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. + +#ifndef THIRD_PARTY_NEARBY_PRESENCE_BROADCAST_OPTIONS_H_ +#define THIRD_PARTY_NEARBY_PRESENCE_BROADCAST_OPTIONS_H_ + +#include +namespace nearby { +namespace presence { +struct BroadcastOptions { + const std::int64_t reporting_interval_millis; +}; + +inline bool operator==(const BroadcastOptions& o1, const BroadcastOptions& o2) { + return o1.reporting_interval_millis == o2.reporting_interval_millis; +} + +inline bool operator!=(const BroadcastOptions& o1, const BroadcastOptions& o2) { + return !(o1 == o2); +} + +} // namespace presence +} // namespace nearby + +#endif // THIRD_PARTY_NEARBY_PRESENCE_BROADCAST_OPTIONS_H_ diff --git a/presence/broadcast_options_test.cc b/presence/broadcast_options_test.cc new file mode 100644 index 00000000..22b16202 --- /dev/null +++ b/presence/broadcast_options_test.cc @@ -0,0 +1,53 @@ +// Copyright 2020 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 +// +// https://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 "third_party/nearby/presence/broadcast_options.h" + +#include "gmock/gmock.h" +#include "protobuf-matchers/protocol-buffer-matchers.h" +#include "gtest/gtest.h" + +namespace nearby { +namespace presence { +namespace { + +constexpr std::int64_t kReportingIntervalMillis1 = 1000; +constexpr std::int64_t kReportingIntervalMillis2 = 2000; +TEST(BroadcastOptionsTest, NoDefaultConstructor) { + EXPECT_FALSE(std::is_trivially_constructible::value); +} + +TEST(BroadcastOptionsTest, ExplicitInitEquals) { + BroadcastOptions option1 = {kReportingIntervalMillis1}; + BroadcastOptions option2 = {kReportingIntervalMillis1}; + EXPECT_EQ(option1, option2); + EXPECT_EQ(option1.reporting_interval_millis, kReportingIntervalMillis1); +} + +TEST(BroadcastOptionsTest, ExplicitInitNotEquals) { + BroadcastOptions option1 = {kReportingIntervalMillis1}; + BroadcastOptions option2 = {kReportingIntervalMillis2}; + EXPECT_NE(option1, option2); +} + +TEST(BroadcastOptionsTest, CopyInitEquals) { + BroadcastOptions option1 = {kReportingIntervalMillis1}; + BroadcastOptions option2 = {option1}; + + EXPECT_EQ(option1, option2); +} + +} // namespace +} // namespace presence +} // namespace nearby diff --git a/presence/listeners.h b/presence/listeners.h new file mode 100644 index 00000000..edd81958 --- /dev/null +++ b/presence/listeners.h @@ -0,0 +1,37 @@ +// Copyright 2020 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 +// +// https://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. + +#ifndef THIRD_PARTY_NEARBY_PRESENCE_LISTENERS_H_ +#define THIRD_PARTY_NEARBY_PRESENCE_LISTENERS_H_ + +#include "internal/platform/listeners.h" +#include "third_party/nearby/presence/status.h" + +namespace nearby { +namespace presence { + +// Common callback for asynchronously invoked methods. +// Called after a job scheduled for execution is completed. +struct ResultCallback { + // Callback to access the status of the operation when available. + // status - result of job execution; + // Status::kSuccess, if successful; anything else indicates failure. + std::function result_cb = + location::nearby::DefaultCallback(); +}; + +} // namespace presence +} // namespace nearby + +#endif // THIRD_PARTY_NEARBY_PRESENCE_LISTENERS_H_ diff --git a/presence/presence_client.cc b/presence/presence_client.cc new file mode 100644 index 00000000..fc04c2dc --- /dev/null +++ b/presence/presence_client.cc @@ -0,0 +1,49 @@ +// Copyright 2020 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 +// +// https://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 "third_party/nearby/presence/presence_client.h" + +#include "third_party/nearby/presence/presence_device.h" + +namespace nearby { +namespace presence { + +void PresenceClient::StartDiscovery(const DiscoveryFilter& filter, + const DiscoveryOptions& options, + ResultCallback callback) {} + +void PresenceClient::UpdateDiscoveryFilter(const DiscoveryFilter& filter, + ResultCallback callback) {} + +void PresenceClient::StopDiscovery(ResultCallback callback) {} + +std::vector PresenceClient::GetCachedDevices( + const DiscoveryFilter& filter) { + return std::vector{}; +} + +void PresenceClient::StartBroadcast(const PresenceIdentity& identity, + const std::vector& actions, + const BroadcastOptions& options, + ResultCallback callback) {} + +void PresenceClient::UpdateBroadcastActions( + const PresenceIdentity& identity, + const std::vector& actions, ResultCallback callback) {} + +void PresenceClient::StopBroadcast(const PresenceIdentity& identity, + ResultCallback callback) {} + +} // namespace presence +} // namespace nearby diff --git a/presence/presence_client.h b/presence/presence_client.h new file mode 100644 index 00000000..3ad97115 --- /dev/null +++ b/presence/presence_client.h @@ -0,0 +1,149 @@ +// Copyright 2020 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 +// +// https://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. + +#ifndef THIRD_PARTY_NEARBY_PRESENCE_PRESENCE_CLIENT_H_ +#define THIRD_PARTY_NEARBY_PRESENCE_PRESENCE_CLIENT_H_ + +#include + +#include "third_party/nearby/presence/broadcast_options.h" +#include "third_party/nearby/presence/discovery_filter.h" +#include "third_party/nearby/presence/discovery_options.h" +#include "third_party/nearby/presence/listeners.h" +#include "third_party/nearby/presence/presence_device.h" + +namespace nearby { +namespace presence { + +/** + * Interface for detecting and interacting with nearby devices that are also + * part of the Presence ecosystem. + */ +class PresenceClient { + public: + /** + * Discovery APIs. + */ + + /** + * Starts a Nearby Presence discovery and registers {@link ResultCallback} + * which will be invoked when a matching {@link PresenceDevice} is detected + * by the service. + * + *

The {@link ResultCallback} is registered at the Nearby Presence service. + * And a same callback can only be registered once. + * + *

The returned {@link Task} may contain the value {@link + * PresenceStatusCodes#RESOLUTION_REQUIRED}. If that is the case, client + * should call {@link Status#startResolutionForResult} to get the users + * consents/permissions before retrying the request. + */ + + void StartDiscovery(const DiscoveryFilter& filter, + const DiscoveryOptions& options, ResultCallback callback); + + /** + * Update the discovery filter for an ongoing discovery. + * + *

The returned {@link Task} may contain the value + * {@link PresenceStatusCodes#RESOLUTION_REQUIRED}. If that is the case, + * client should call {@link Status#startResolutionForResult} to get the users + * consents/permissions before retrying the request. + */ + void UpdateDiscoveryFilter(const DiscoveryFilter& filter, + ResultCallback callback); + + /** + * Stops a Nearby Presence discovery and unregisters a {@link + * DiscoveryCallback} which was previously registered with {@link + * #startDiscovery}. + * + *

If the callback wasn't previously registered, then this will be silently + * ignored. Presence stops discovery, if no client is requesting discovery. + */ + void StopDiscovery(ResultCallback callback); + + /** + * Gets all devices which Presence has recently detected to be within range + * and matching a given {@link DiscoveryFilter}. + * + *

There may be devices within proximity which are not returned as part of + * this method because they haven't yet been discovered by Presence's + * scanning. Apps can call this method multiple times to get the most + * up-to-date information about what is around, however calling it does not + * initiate any scans to find more devices, scanning is handled out-of-band + * from this API. + * + *

Alternatively, clients can use {@link #startDiscovery} to be notified + * when a device is discovered nearby, if the client would like to retrieve + * live devices and their ranging data. + */ + std::vector GetCachedDevices(const DiscoveryFilter& filter); + + /** + * Advertising APIs. + */ + + /** + * Requests that an {@link PresenceIdentity} and associated {@link + * PresenceAction}s be broadcast to other devices nearby. + * + *

These actions can then be detected by those devices and trigger a + * callback to a client which as invoked {@link #startDiscovery} for the same + * action. + * + *

Clients set a {@link PresenceIdentity} to determine who should be able + * to resolve their advertisements. + * + *

One client can advertise up to one advertisement per identity. Due to + * hardware capabilities, Presence needs to rotate advertisement or release + * resources. Frequent callers might be throttled based on resource + * limitations. + * + *

The returned {@link Task} may contain the value {@link + * PresenceStatusCodes#RESOLUTION_REQUIRED}. If that is the case, client + * should call {@linkStatus#startResolutionForResult} to get the users + * consents/permissions before retrying the request. + */ + void StartBroadcast(const PresenceIdentity& identity, + const std::vector& actions, + const BroadcastOptions& options, ResultCallback callback); + + /** + * Updates {@link PresenceAction}s of an ongoing advertising for a + * {@link PresenceIdentity}. + * + *

The returned {@link Task} may contain the value {@link + * PresenceStatusCodes#RESOLUTION_REQUIRED}. If that is the case, client + * should call {@link Status#startResolutionForResult} to get the users + * consents/permissions before retrying the request. + */ + void UpdateBroadcastActions(const PresenceIdentity& identity, + const std::vector& actions, + ResultCallback callback); + + /** + * Removes an identity broadcast that was currently requested via + * {@link #startBroadcast}. + * + *

This should be invoked after the use case has been fulfilled and the + * device no longer needs remote devices to know that it is nearby. + */ + void StopBroadcast(const PresenceIdentity& identity, ResultCallback callback); +}; + +} // namespace presence +} // namespace nearby + +#endif // THIRD_PARTY_NEARBY_PRESENCE_PRESENCE_CLIENT_H_ diff --git a/presence/presence_client_test.cc b/presence/presence_client_test.cc new file mode 100644 index 00000000..d8f81e5d --- /dev/null +++ b/presence/presence_client_test.cc @@ -0,0 +1,32 @@ +// Copyright 2020 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 +// +// https://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 "third_party/nearby/presence/presence_client.h" + +#include "gmock/gmock.h" +#include "protobuf-matchers/protocol-buffer-matchers.h" +#include "gtest/gtest.h" + +namespace nearby { +namespace presence { +namespace { + +TEST(PresenceClientTest, DefaultConstructorWorks) { + PresenceClient presence_client; + presence_client.StartBroadcast({}, {}, {}, {}); +} + +} // namespace +} // namespace presence +} // namespace nearby diff --git a/presence/presence_device.cc b/presence/presence_device.cc new file mode 100644 index 00000000..90cef494 --- /dev/null +++ b/presence/presence_device.cc @@ -0,0 +1,31 @@ +// Copyright 2020 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 +// +// https://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 "third_party/nearby/presence/presence_device.h" + +namespace nearby { +namespace presence { + +PresenceDevice::PresenceDevice(PresenceDevice::MotionType type, + float confidence) noexcept + : motion_type_(type), confidence_(confidence) {} + +PresenceDevice::MotionType PresenceDevice::GetMotionType() const { + return motion_type_; +} + +float PresenceDevice::GetConfidence() const { return confidence_; } + +} // namespace presence +} // namespace nearby diff --git a/presence/presence_device.h b/presence/presence_device.h new file mode 100644 index 00000000..bfb4ce91 --- /dev/null +++ b/presence/presence_device.h @@ -0,0 +1,47 @@ +// Copyright 2020 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 +// +// https://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. + +#ifndef THIRD_PARTY_NEARBY_PRESENCE_PRESENCE_DEVICE_H_ +#define THIRD_PARTY_NEARBY_PRESENCE_PRESENCE_DEVICE_H_ + +namespace nearby { +namespace presence { +class PresenceDevice { + public: + enum class MotionType { + kPointAndHold = 0, + }; + PresenceDevice(MotionType type = MotionType::kPointAndHold, + float confidence = 0) noexcept; + MotionType GetMotionType() const; + float GetConfidence() const; + + private: + const MotionType motion_type_; + const float confidence_; +}; + +inline bool operator==(const PresenceDevice& d1, const PresenceDevice& d2) { + return d1.GetMotionType() == d2.GetMotionType() && + d1.GetConfidence() == d2.GetConfidence(); +} + +inline bool operator!=(const PresenceDevice& d1, const PresenceDevice& d2) { + return !(d1 == d2); +} + +} // namespace presence +} // namespace nearby + +#endif // THIRD_PARTY_NEARBY_PRESENCE_PRESENCE_DEVICE_H_ diff --git a/presence/presence_device_test.cc b/presence/presence_device_test.cc new file mode 100644 index 00000000..2025a9cd --- /dev/null +++ b/presence/presence_device_test.cc @@ -0,0 +1,60 @@ +// Copyright 2020 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 +// +// https://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 "third_party/nearby/presence/presence_device.h" + +#include "gmock/gmock.h" +#include "protobuf-matchers/protocol-buffer-matchers.h" +#include "gtest/gtest.h" + +namespace nearby { +namespace presence { +namespace { +constexpr PresenceDevice::MotionType kDefaultMotionType = + PresenceDevice::MotionType::kPointAndHold; +constexpr float kDefaultConfidence = 0; +constexpr float kTestConfidence = 0.1; +TEST(PresenceDeviceTest, DefaultConstructorWorks) { + PresenceDevice device; + EXPECT_EQ(device.GetMotionType(), kDefaultMotionType); + EXPECT_EQ(device.GetConfidence(), kDefaultConfidence); +} + +TEST(PresenceDeviceTest, DefaultEquals) { + PresenceDevice device1; + PresenceDevice device2; + EXPECT_EQ(device1, device2); +} + +TEST(PresenceDeviceTest, ExplicitInitEquals) { + PresenceDevice device1 = {kDefaultMotionType, kTestConfidence}; + PresenceDevice device2 = {kDefaultMotionType, kTestConfidence}; + EXPECT_EQ(device1, device2); +} + +TEST(PresenceDeviceTest, ExplicitInitNotEquals) { + PresenceDevice device1 = {kDefaultMotionType}; + PresenceDevice device2 = {kDefaultMotionType, kTestConfidence}; + EXPECT_NE(device1, device2); +} + +TEST(PresenceDeviceTest, CopyInitEquals) { + PresenceDevice device1 = {kDefaultMotionType, kTestConfidence}; + PresenceDevice device2 = {device1}; + EXPECT_EQ(device1, device2); +} + +} // namespace +} // namespace presence +} // namespace nearby diff --git a/presence/presence_zone.h b/presence/presence_zone.h index 9b8509a5..2f3c7661 100644 --- a/presence/presence_zone.h +++ b/presence/presence_zone.h @@ -36,8 +36,9 @@ class PresenceZone { kWithinTap, // Distance is within tap range to the peer device, typically // within ~0.127 meters. }; - DistanceBoundary(float = 0, float = 0, - RangeType = RangeType::kRangeUnknown) noexcept; + DistanceBoundary(float min_distance_meters = 0, + float max_distance_meters = 0, + RangeType range_type = RangeType::kRangeUnknown) noexcept; float GetMinDistanceMeters() const; float GetMaxDistanceMeters() const; RangeType GetRangeType() const; @@ -50,7 +51,8 @@ class PresenceZone { class AngleOfArrivalBoundary { public: - AngleOfArrivalBoundary(float = 0, float = 0) noexcept; + AngleOfArrivalBoundary(float min_angle_degrees = 0, + float max_angle_degrees = 0) noexcept; float GetMinAngleDegrees() const; float GetMaxAngleDegrees() const; diff --git a/presence/status.h b/presence/status.h new file mode 100644 index 00000000..84713fe0 --- /dev/null +++ b/presence/status.h @@ -0,0 +1,43 @@ +// Copyright 2020 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 +// +// https://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. + +#ifndef THIRD_PARTY_NEARBY_PRESENCE_STATUS_H_ +#define THIRD_PARTY_NEARBY_PRESENCE_STATUS_H_ + +namespace nearby { +namespace presence { +// Protocol operation result: kSuccess, if operation was successful; +// descriptive error code otherwise. +struct Status { + // Status is a struct, so it is possible to pass some context about failure, + // by adding extra fields to it when necessary, and not change any of the + // method signatures. + enum class Value { + kError = 0, + kSuccess, + }; + Value value{Value::kError}; + bool Ok() const { return value == Value::kSuccess; } +}; + +inline bool operator==(const Status& a, const Status& b) { + return a.value == b.value; +} + +inline bool operator!=(const Status& a, const Status& b) { return !(a == b); } + +} // namespace presence +} // namespace nearby + +#endif // THIRD_PARTY_NEARBY_PRESENCE_STATUS_H_ diff --git a/presence/status_test.cc b/presence/status_test.cc new file mode 100644 index 00000000..24c114d7 --- /dev/null +++ b/presence/status_test.cc @@ -0,0 +1,58 @@ +// Copyright 2020 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 +// +// https://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 "third_party/nearby/presence/status.h" + +#include "gmock/gmock.h" +#include "protobuf-matchers/protocol-buffer-matchers.h" +#include "gtest/gtest.h" + +namespace nearby { +namespace presence { +namespace { + +TEST(StatusTest, DefaultIsError) { + Status status; + EXPECT_FALSE(status.Ok()); + EXPECT_EQ(status, Status{Status::Value::kError}); +} + +TEST(StatusTest, DefaultEquals) { + Status status1; + Status status2; + EXPECT_EQ(status1, status2); +} + +TEST(StatusTest, ExplicitInitEquals) { + Status status1 = {Status::Value::kSuccess}; + Status status2 = {Status::Value::kSuccess}; + EXPECT_EQ(status1, status2); + EXPECT_TRUE(status1.Ok()); +} + +TEST(StatusTest, ExplicitInitNotEquals) { + Status status1 = {Status::Value::kSuccess}; + Status status2 = {Status::Value::kError}; + EXPECT_NE(status1, status2); +} + +TEST(StatusTest, CopyInitEquals) { + Status status1 = {Status::Value::kSuccess}; + Status status2 = {status1}; + EXPECT_EQ(status1, status2); +} + +} // namespace +} // namespace presence +} // namespace nearby