Update VTS tests to support the latest BiometricsFace.hal

Bug: 134967390
Test: vts-tradefed run commandAndExit vts-hal -m VtsHalBiometricsFaceV1_0Target
Change-Id: Ifbd04d127626315efd8c8ce36636e550cbb843ff
diff --git a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
index 40961f7..d3d7387 100644
--- a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
+++ b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
@@ -14,29 +14,24 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "face_hidl_test"
+#define LOG_TAG "biometrics_face_hidl_hal_test"
 
+#include <android/hardware/biometrics/face/1.0/IBiometricsFace.h>
+#include <android/hardware/biometrics/face/1.0/IBiometricsFaceClientCallback.h>
+
+#include <VtsHalHidlTargetCallbackBase.h>
 #include <VtsHalHidlTargetTestBase.h>
 #include <VtsHalHidlTargetTestEnvBase.h>
 #include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android/hardware/biometrics/face/1.0/IBiometricsFace.h>
-#include <android/hardware/biometrics/face/1.0/IBiometricsFaceClientCallback.h>
-#include <hidl/HidlSupport.h>
-#include <hidl/HidlTransportSupport.h>
-#include <utils/Condition.h>
 
-#include <cinttypes>
+#include <chrono>
 #include <cstdint>
-#include <future>
-#include <utility>
+#include <random>
 
-using android::Condition;
-using android::Mutex;
 using android::sp;
-using android::base::GetUintProperty;
 using android::hardware::hidl_vec;
 using android::hardware::Return;
+using android::hardware::Void;
 using android::hardware::biometrics::face::V1_0::FaceAcquiredInfo;
 using android::hardware::biometrics::face::V1_0::FaceError;
 using android::hardware::biometrics::face::V1_0::Feature;
@@ -48,263 +43,203 @@
 
 namespace {
 
-const uint32_t kTimeout = 3;
-const std::chrono::seconds kTimeoutInSeconds = std::chrono::seconds(kTimeout);
-const uint32_t kUserId = 99;
-const uint32_t kFaceId = 5;
-const char kTmpDir[] = "/data/system/users/0/facedata";
-const int kIterations = 1000;
+// Arbitrary, nonexistent userId
+constexpr uint32_t kUserId = 9;
+// Arbitrary, nonexistent faceId
+constexpr uint32_t kFaceId = 5;
+constexpr uint32_t kTimeoutSec = 3;
+constexpr auto kTimeout = std::chrono::seconds(kTimeoutSec);
+constexpr int kGenerateChallengeIterations = 10;
+constexpr char kFacedataDir[] = "/data/vendor_de/0/facedata";
+constexpr char kCallbackNameOnEnrollResult[] = "onEnrollResult";
+constexpr char kCallbackNameOnAuthenticated[] = "onAuthenticated";
+constexpr char kCallbackNameOnAcquired[] = "onAcquired";
+constexpr char kCallbackNameOnError[] = "onError";
+constexpr char kCallbackNameOnRemoved[] = "onRemoved";
+constexpr char kCallbackNameOnEnumerate[] = "onEnumerate";
+constexpr char kCallbackNameOnLockoutChanged[] = "onLockoutChanged";
 
-const auto kAssertCallbackIsSet = [](const OptionalUint64& res) {
-    ASSERT_EQ(Status::OK, res.status);
-    // Makes sure the "deviceId" represented by "res.value" is not 0.
-    // 0 would mean the HIDL is not available.
-    ASSERT_NE(0UL, res.value);
+// Callback arguments that need to be captured for the tests.
+struct FaceCallbackArgs {
+    // The error passed to the last onError() callback.
+    FaceError error;
+
+    // The userId passed to the last onRemoved() callback.
+    int32_t userId;
 };
 
-// Wait for a callback to occur (signaled by the given future) up to the
-// provided timeout. If the future is invalid or the callback does not come
-// within the given time, returns false.
-template <class ReturnType>
-bool waitForCallback(std::future<ReturnType> future,
-                     std::chrono::milliseconds timeout = kTimeoutInSeconds) {
-    auto expiration = std::chrono::system_clock::now() + timeout;
-    EXPECT_TRUE(future.valid());
-    if (future.valid()) {
-        std::future_status status = future.wait_until(expiration);
-        EXPECT_NE(std::future_status::timeout, status) << "Timed out waiting for callback";
-        if (status == std::future_status::ready) {
-            return true;
-        }
-    }
-    return false;
-}
-
-// Base callback implementation that just logs all callbacks by default
-class FaceCallbackBase : public IBiometricsFaceClientCallback {
+// Test callback class for the BiometricsFace HAL.
+// The HAL will call these callback methods to notify about completed operations
+// or encountered errors.
+class FaceCallback : public ::testing::VtsHalHidlTargetCallbackBase<FaceCallbackArgs>,
+                     public IBiometricsFaceClientCallback {
   public:
     Return<void> onEnrollResult(uint64_t, uint32_t, int32_t, uint32_t) override {
-        ALOGD("Enroll callback called.");
-        return Return<void>();
+        NotifyFromCallback(kCallbackNameOnEnrollResult);
+        return Void();
     }
 
     Return<void> onAuthenticated(uint64_t, uint32_t, int32_t, const hidl_vec<uint8_t>&) override {
-        ALOGD("Authenticated callback called.");
-        return Return<void>();
+        NotifyFromCallback(kCallbackNameOnAuthenticated);
+        return Void();
     }
 
     Return<void> onAcquired(uint64_t, int32_t, FaceAcquiredInfo, int32_t) override {
-        ALOGD("Acquired callback called.");
-        return Return<void>();
+        NotifyFromCallback(kCallbackNameOnAcquired);
+        return Void();
     }
 
-    Return<void> onError(uint64_t, int32_t, FaceError, int32_t) override {
-        ALOGD("Error callback called.");
-        EXPECT_TRUE(false);  // fail any test that triggers an error
-        return Return<void>();
+    Return<void> onError(uint64_t, int32_t, FaceError error, int32_t) override {
+        FaceCallbackArgs args = {};
+        args.error = error;
+        NotifyFromCallback(kCallbackNameOnError, args);
+        return Void();
     }
 
-    Return<void> onRemoved(uint64_t, const hidl_vec<uint32_t>&, int32_t) override {
-        ALOGD("Removed callback called.");
-        return Return<void>();
+    Return<void> onRemoved(uint64_t, const hidl_vec<uint32_t>&, int32_t userId) override {
+        FaceCallbackArgs args = {};
+        args.userId = userId;
+        NotifyFromCallback(kCallbackNameOnRemoved, args);
+        return Void();
     }
 
-    Return<void> onEnumerate(uint64_t, const hidl_vec<uint32_t>&, int32_t /* userId */) override {
-        ALOGD("Enumerate callback called.");
-        return Return<void>();
+    Return<void> onEnumerate(uint64_t, const hidl_vec<uint32_t>&, int32_t) override {
+        NotifyFromCallback(kCallbackNameOnEnumerate);
+        return Void();
     }
 
     Return<void> onLockoutChanged(uint64_t) override {
-        ALOGD("LockoutChanged callback called.");
-        return Return<void>();
+        NotifyFromCallback(kCallbackNameOnLockoutChanged);
+        return Void();
     }
 };
 
-class EnumerateCallback : public FaceCallbackBase {
-  public:
-    Return<void> onEnumerate(uint64_t, const hidl_vec<uint32_t>&, int32_t) override {
-        promise.set_value();
-        return Return<void>();
-    }
-
-    std::promise<void> promise;
-};
-
-class ErrorCallback : public FaceCallbackBase {
-  public:
-    ErrorCallback(bool filterErrors = false, FaceError errorType = FaceError::HW_UNAVAILABLE)
-        : filterErrors(filterErrors), errorType(errorType), hasError(false) {}
-
-    Return<void> onError(uint64_t, int32_t, FaceError error, int32_t) override {
-        if ((filterErrors && errorType == error) || !filterErrors) {
-            hasError = true;
-            this->error = error;
-            promise.set_value();
-        }
-        return Return<void>();
-    }
-
-    bool filterErrors;
-    FaceError errorType;
-    bool hasError;
-    FaceError error;
-    std::promise<void> promise;
-};
-
-class RemoveCallback : public FaceCallbackBase {
-  public:
-    explicit RemoveCallback(int32_t userId) : removeUserId(userId) {}
-
-    Return<void> onRemoved(uint64_t, const hidl_vec<uint32_t>&, int32_t userId) override {
-        EXPECT_EQ(removeUserId, userId);
-        promise.set_value();
-        return Return<void>();
-    }
-
-    int32_t removeUserId;
-    std::promise<void> promise;
-};
-
-class LockoutChangedCallback : public FaceCallbackBase {
-  public:
-    Return<void> onLockoutChanged(uint64_t duration) override {
-        this->hasDuration = true;
-        this->duration = duration;
-        promise.set_value();
-        return Return<void>();
-    }
-    bool hasDuration;
-    uint64_t duration;
-    std::promise<void> promise;
-};
-
-// Test environment for Face HIDL HAL.
+// Test environment for the BiometricsFace HAL.
 class FaceHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
   public:
-    // get the test environment singleton
+    // Get the test environment singleton.
     static FaceHidlEnvironment* Instance() {
         static FaceHidlEnvironment* instance = new FaceHidlEnvironment;
         return instance;
     }
 
     void registerTestServices() override { registerTestService<IBiometricsFace>(); }
+
+  private:
+    FaceHidlEnvironment() = default;
 };
 
+// Test class for the BiometricsFace HAL.
 class FaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
   public:
     void SetUp() override {
         mService = ::testing::VtsHalHidlTargetTestBase::getService<IBiometricsFace>(
                 FaceHidlEnvironment::Instance()->getServiceName<IBiometricsFace>());
-        ASSERT_FALSE(mService == nullptr);
-        Return<Status> res = mService->setActiveUser(kUserId, kTmpDir);
-        ASSERT_EQ(Status::OK, static_cast<Status>(res));
+        ASSERT_NE(mService, nullptr);
+        mCallback = new FaceCallback();
+        mCallback->SetWaitTimeoutDefault(kTimeout);
+        Return<void> ret1 = mService->setCallback(mCallback, [](const OptionalUint64& res) {
+            ASSERT_EQ(Status::OK, res.status);
+            // Makes sure the "deviceId" represented by "res.value" is not 0.
+            // 0 would mean the HIDL is not available.
+            ASSERT_NE(0UL, res.value);
+        });
+        ASSERT_TRUE(ret1.isOk());
+        Return<Status> ret2 = mService->setActiveUser(kUserId, kFacedataDir);
+        ASSERT_EQ(Status::OK, static_cast<Status>(ret2));
     }
 
     void TearDown() override {}
 
     sp<IBiometricsFace> mService;
+    sp<FaceCallback> mCallback;
 };
 
-// The service should be reachable.
-TEST_F(FaceHidlTest, ConnectTest) {
-    sp<FaceCallbackBase> cb = new FaceCallbackBase();
-    mService->setCallback(cb, kAssertCallbackIsSet);
-}
-
-// Starting the service with null callback should succeed.
-TEST_F(FaceHidlTest, ConnectNullTest) {
-    mService->setCallback(nullptr, kAssertCallbackIsSet);
-}
-
 // generateChallenge should always return a unique, cryptographically secure,
 // non-zero number.
 TEST_F(FaceHidlTest, GenerateChallengeTest) {
     std::map<uint64_t, int> m;
-    for (int i = 0; i < kIterations; ++i) {
-        mService->generateChallenge(kTimeout, [&m](const OptionalUint64& res) {
-            ASSERT_EQ(Status::OK, res.status);
-            EXPECT_NE(0UL, res.value);
-            m[res.value]++;
-            EXPECT_EQ(1UL, m[res.value]);
-        });
+    for (int i = 0; i < kGenerateChallengeIterations; ++i) {
+        Return<void> ret =
+                mService->generateChallenge(kTimeoutSec, [&m](const OptionalUint64& res) {
+                    ASSERT_EQ(Status::OK, res.status);
+                    EXPECT_NE(0UL, res.value);
+                    m[res.value]++;
+                    EXPECT_EQ(1UL, m[res.value]);
+                });
+        ASSERT_TRUE(ret.isOk());
     }
 }
 
 // enroll with an invalid (all zeroes) HAT should fail.
 TEST_F(FaceHidlTest, EnrollZeroHatTest) {
-    sp<ErrorCallback> cb = new ErrorCallback();
-    mService->setCallback(cb, kAssertCallbackIsSet);
-
+    // Filling HAT with zeros
     hidl_vec<uint8_t> token(69);
     for (size_t i = 0; i < 69; i++) {
         token[i] = 0;
     }
 
-    Return<Status> res = mService->enroll(token, kTimeout, {});
-    ASSERT_EQ(Status::OK, static_cast<Status>(res));
+    Return<Status> ret = mService->enroll(token, kTimeoutSec, {});
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
 
-    // At least one call to onError should occur
-    ASSERT_TRUE(waitForCallback(cb->promise.get_future()));
-    ASSERT_TRUE(cb->hasError);
+    // onError should be called with a meaningful (nonzero) error.
+    auto res = mCallback->WaitForCallback(kCallbackNameOnError);
+    EXPECT_TRUE(res.no_timeout);
+    EXPECT_EQ(FaceError::UNABLE_TO_PROCESS, res.args->error);
 }
 
 // enroll with an invalid HAT should fail.
 TEST_F(FaceHidlTest, EnrollGarbageHatTest) {
-    sp<ErrorCallback> cb = new ErrorCallback();
-    mService->setCallback(cb, kAssertCallbackIsSet);
-
-    // Filling HAT with invalid data
+    // Filling HAT with pseudorandom invalid data.
+    // Using default seed to make the test reproducible.
+    std::mt19937 gen(std::mt19937::default_seed);
+    std::uniform_int_distribution<uint8_t> dist;
     hidl_vec<uint8_t> token(69);
     for (size_t i = 0; i < 69; ++i) {
-        token[i] = i;
+        token[i] = dist(gen);
     }
 
-    Return<Status> res = mService->enroll(token, kTimeout, {});
-    ASSERT_EQ(Status::OK, static_cast<Status>(res));
+    Return<Status> ret = mService->enroll(token, kTimeoutSec, {});
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
 
-    // At least one call to onError should occur
-    ASSERT_TRUE(waitForCallback(cb->promise.get_future()));
-    ASSERT_TRUE(cb->hasError);
+    // onError should be called with a meaningful (nonzero) error.
+    auto res = mCallback->WaitForCallback(kCallbackNameOnError);
+    EXPECT_TRUE(res.no_timeout);
+    EXPECT_EQ(FaceError::UNABLE_TO_PROCESS, res.args->error);
 }
 
 // setFeature with an invalid (all zeros) HAT should fail.
 TEST_F(FaceHidlTest, SetFeatureZeroHatTest) {
-    sp<ErrorCallback> cb = new ErrorCallback();
-    mService->setCallback(cb, kAssertCallbackIsSet);
-
     hidl_vec<uint8_t> token(69);
     for (size_t i = 0; i < 69; i++) {
         token[i] = 0;
     }
 
-    Return<Status> res = mService->setFeature(Feature::REQUIRE_DIVERSITY, false, token, 0);
-    ASSERT_EQ(Status::ILLEGAL_ARGUMENT, static_cast<Status>(res));
+    Return<Status> ret = mService->setFeature(Feature::REQUIRE_DIVERSITY, false, token, 0);
+    ASSERT_EQ(Status::ILLEGAL_ARGUMENT, static_cast<Status>(ret));
 }
 
 // setFeature with an invalid HAT should fail.
 TEST_F(FaceHidlTest, SetFeatureGarbageHatTest) {
-    sp<ErrorCallback> cb = new ErrorCallback();
-    mService->setCallback(cb, kAssertCallbackIsSet);
-
-    // Filling HAT with invalid data
+    // Filling HAT with pseudorandom invalid data.
+    // Using default seed to make the test reproducible.
+    std::mt19937 gen(std::mt19937::default_seed);
+    std::uniform_int_distribution<uint8_t> dist;
     hidl_vec<uint8_t> token(69);
     for (size_t i = 0; i < 69; ++i) {
-        token[i] = i;
+        token[i] = dist(gen);
     }
 
-    Return<Status> res = mService->setFeature(Feature::REQUIRE_DIVERSITY, false, token, 0);
-    ASSERT_EQ(Status::ILLEGAL_ARGUMENT, static_cast<Status>(res));
+    Return<Status> ret = mService->setFeature(Feature::REQUIRE_DIVERSITY, false, token, 0);
+    ASSERT_EQ(Status::ILLEGAL_ARGUMENT, static_cast<Status>(ret));
 }
 
-void assertGetFeatureFails(sp<IBiometricsFace> service, int faceId, Feature feature) {
-    std::promise<void> promise;
-
+void assertGetFeatureFails(const sp<IBiometricsFace>& service, uint32_t faceId, Feature feature) {
     // Features cannot be retrieved for invalid faces.
-    Return<void> res = service->getFeature(feature, faceId, [&promise](const OptionalBool& result) {
+    Return<void> res = service->getFeature(feature, faceId, [](const OptionalBool& result) {
         ASSERT_EQ(Status::ILLEGAL_ARGUMENT, result.status);
-        promise.set_value();
     });
-    ASSERT_TRUE(waitForCallback(promise.get_future()));
+    ASSERT_TRUE(res.isOk());
 }
 
 TEST_F(FaceHidlTest, GetFeatureRequireAttentionTest) {
@@ -317,111 +252,95 @@
 
 // revokeChallenge should always return within the timeout
 TEST_F(FaceHidlTest, RevokeChallengeTest) {
-    sp<FaceCallbackBase> cb = new FaceCallbackBase();
-    mService->setCallback(cb, kAssertCallbackIsSet);
-
     auto start = std::chrono::system_clock::now();
-    mService->revokeChallenge();
+    Return<Status> ret = mService->revokeChallenge();
     auto elapsed = std::chrono::system_clock::now() - start;
-    ASSERT_GE(kTimeoutInSeconds, elapsed);
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
+    ASSERT_GE(kTimeout, elapsed);
 }
 
 // The call to getAuthenticatorId should succeed.
 TEST_F(FaceHidlTest, GetAuthenticatorIdTest) {
-    mService->getAuthenticatorId(
+    Return<void> ret = mService->getAuthenticatorId(
             [](const OptionalUint64& res) { ASSERT_EQ(Status::OK, res.status); });
+    ASSERT_TRUE(ret.isOk());
 }
 
 // The call to enumerate should succeed.
 TEST_F(FaceHidlTest, EnumerateTest) {
-    sp<EnumerateCallback> cb = new EnumerateCallback();
-    mService->setCallback(cb, kAssertCallbackIsSet);
-    Return<Status> res = mService->enumerate();
-    ASSERT_EQ(Status::OK, static_cast<Status>(res));
-    ASSERT_TRUE(waitForCallback(cb->promise.get_future()));
+    Return<Status> ret = mService->enumerate();
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
+    auto res = mCallback->WaitForCallback(kCallbackNameOnEnumerate);
+    EXPECT_TRUE(res.no_timeout);
 }
 
 // The call to remove should succeed for any faceId
 TEST_F(FaceHidlTest, RemoveFaceTest) {
-    sp<ErrorCallback> cb = new ErrorCallback();
-    mService->setCallback(cb, kAssertCallbackIsSet);
-
     // Remove a face
-    Return<Status> res = mService->remove(kFaceId);
-    ASSERT_EQ(Status::OK, static_cast<Status>(res));
+    Return<Status> ret = mService->remove(kFaceId);
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
 }
 
 // Remove should accept 0 to delete all faces
 TEST_F(FaceHidlTest, RemoveAllFacesTest) {
-    sp<ErrorCallback> cb = new ErrorCallback();
-    mService->setCallback(cb, kAssertCallbackIsSet);
-
     // Remove all faces
-    Return<Status> res = mService->remove(0);
-    ASSERT_EQ(Status::OK, static_cast<Status>(res));
+    Return<Status> ret = mService->remove(0);
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
 }
 
 // Active user should successfully set to a writable location.
 TEST_F(FaceHidlTest, SetActiveUserTest) {
     // Create an active user
-    Return<Status> res = mService->setActiveUser(2, kTmpDir);
-    ASSERT_EQ(Status::OK, static_cast<Status>(res));
+    Return<Status> ret = mService->setActiveUser(2, kFacedataDir);
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
 
     // Reset active user
-    res = mService->setActiveUser(kUserId, kTmpDir);
-    ASSERT_EQ(Status::OK, static_cast<Status>(res));
+    ret = mService->setActiveUser(kUserId, kFacedataDir);
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
 }
 
 // Active user should fail to set to an unwritable location.
 TEST_F(FaceHidlTest, SetActiveUserUnwritableTest) {
     // Create an active user to an unwritable location (device root dir)
-    Return<Status> res = mService->setActiveUser(3, "/");
-    ASSERT_NE(Status::OK, static_cast<Status>(res));
+    Return<Status> ret = mService->setActiveUser(3, "/");
+    ASSERT_NE(Status::OK, static_cast<Status>(ret));
 
     // Reset active user
-    res = mService->setActiveUser(kUserId, kTmpDir);
-    ASSERT_EQ(Status::OK, static_cast<Status>(res));
+    ret = mService->setActiveUser(kUserId, kFacedataDir);
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
 }
 
 // Active user should fail to set to a null location.
 TEST_F(FaceHidlTest, SetActiveUserNullTest) {
     // Create an active user to a null location.
-    Return<Status> res = mService->setActiveUser(4, nullptr);
-    ASSERT_NE(Status::OK, static_cast<Status>(res));
+    Return<Status> ret = mService->setActiveUser(4, nullptr);
+    ASSERT_NE(Status::OK, static_cast<Status>(ret));
 
     // Reset active user
-    res = mService->setActiveUser(kUserId, kTmpDir);
-    ASSERT_EQ(Status::OK, static_cast<Status>(res));
+    ret = mService->setActiveUser(kUserId, kFacedataDir);
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
 }
 
 // Cancel should always return CANCELED from any starting state including
 // the IDLE state.
 TEST_F(FaceHidlTest, CancelTest) {
-    sp<ErrorCallback> cb = new ErrorCallback(true, FaceError::CANCELED);
-    mService->setCallback(cb, kAssertCallbackIsSet);
-
-    Return<Status> res = mService->cancel();
+    Return<Status> ret = mService->cancel();
     // check that we were able to make an IPC request successfully
-    ASSERT_EQ(Status::OK, static_cast<Status>(res));
-
-    // make sure callback was invoked within kTimeoutInSeconds
-    ASSERT_TRUE(waitForCallback(cb->promise.get_future()));
-    // check error should be CANCELED
-    ASSERT_EQ(FaceError::CANCELED, cb->error);
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
+    auto res = mCallback->WaitForCallback(kCallbackNameOnError);
+    // make sure callback was invoked within kRevokeChallengeTimeout
+    EXPECT_TRUE(res.no_timeout);
+    EXPECT_EQ(FaceError::CANCELED, res.args->error);
 }
 
 TEST_F(FaceHidlTest, OnLockoutChangedTest) {
-    sp<LockoutChangedCallback> cb = new LockoutChangedCallback();
-    mService->setCallback(cb, kAssertCallbackIsSet);
-
-    // Update active user and ensure lockout duration 0 is received
-    mService->setActiveUser(5, kTmpDir);
+    // Update active user and ensure onLockoutChanged was called.
+    Return<Status> ret = mService->setActiveUser(kUserId + 1, kFacedataDir);
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
 
     // Make sure callback was invoked
-    ASSERT_TRUE(waitForCallback(cb->promise.get_future()));
-
-    // Check that duration 0 was received
-    ASSERT_EQ(0, cb->duration);
+    auto res = mCallback->WaitForCallback(kCallbackNameOnLockoutChanged);
+    EXPECT_TRUE(res.no_timeout);
 }
 
 }  // anonymous namespace