OSDN Git Service

Add VTS test for ISoundTriggerHw::loadSoundModel
authorHsin-Yi Chen <hsinyichen@google.com>
Mon, 27 Feb 2017 11:29:42 +0000 (19:29 +0800)
committerHsin-Yi Chen <hsinyichen@google.com>
Fri, 3 Mar 2017 03:50:02 +0000 (11:50 +0800)
Add a negative test for loading generic sound model with random data.

Test: vts-tradefed run commandAndExit vts -m VtsHalSoundtriggerV2_0Target
Bug: 35409266
Change-Id: I0bb6dd758d114bd094c88899abf06accdefb8efa

soundtrigger/2.0/vts/functional/VtsHalSoundtriggerV2_0TargetTest.cpp

index 41e7e69..273ee14 100644 (file)
  */
 
 #define LOG_TAG "SoundTriggerHidlHalTest"
+#include <stdlib.h>
+#include <time.h>
+
+#include <condition_variable>
+#include <mutex>
+
 #include <android/log.h>
 #include <cutils/native_handle.h>
 
@@ -24,6 +30,8 @@
 
 #include <VtsHalHidlTargetBaseTest.h>
 
+#define SHORT_TIMEOUT_PERIOD (1)
+
 using ::android::hardware::audio::common::V2_0::AudioDevice;
 using ::android::hardware::soundtrigger::V2_0::SoundModelHandle;
 using ::android::hardware::soundtrigger::V2_0::SoundModelType;
@@ -36,43 +44,101 @@ using ::android::hardware::Status;
 using ::android::hardware::Void;
 using ::android::sp;
 
+/**
+ * Test code uses this class to wait for notification from callback.
+ */
+class Monitor {
+ public:
+  Monitor() : mCount(0) {}
+
+  /**
+   * Adds 1 to the internal counter and unblocks one of the waiting threads.
+   */
+  void notify() {
+    std::unique_lock<std::mutex> lock(mMtx);
+    mCount++;
+    mCv.notify_one();
+  }
+
+  /**
+   * Blocks until the internal counter becomes greater than 0.
+   *
+   * If notified, this method decreases the counter by 1 and returns true.
+   * If timeout, returns false.
+   */
+  bool wait(int timeoutSeconds) {
+    std::unique_lock<std::mutex> lock(mMtx);
+    auto deadline = std::chrono::system_clock::now() +
+        std::chrono::seconds(timeoutSeconds);
+    while (mCount == 0) {
+      if (mCv.wait_until(lock, deadline) == std::cv_status::timeout) {
+        return false;
+      }
+    }
+    mCount--;
+    return true;
+  }
+
+ private:
+  std::mutex mMtx;
+  std::condition_variable mCv;
+  int mCount;
+};
+
 // The main test class for Sound Trigger HIDL HAL.
 class SoundTriggerHidlTest : public ::testing::VtsHalHidlTargetBaseTest {
  public:
   virtual void SetUp() override {
     mSoundTriggerHal = ::testing::VtsHalHidlTargetBaseTest::getService<ISoundTriggerHw>("sound_trigger.primary");
     ASSERT_NE(nullptr, mSoundTriggerHal.get());
-    mCallback = new MyCallback();
+    mCallback = new SoundTriggerHwCallback(*this);
     ASSERT_NE(nullptr, mCallback.get());
   }
 
-  class MyCallback : public ISoundTriggerHwCallback {
-      virtual Return<void> recognitionCallback(
-                  const ISoundTriggerHwCallback::RecognitionEvent& event __unused,
-                  int32_t cookie __unused) {
-          ALOGI("%s", __FUNCTION__);
-          return Void();
-      }
-
-      virtual Return<void> phraseRecognitionCallback(
-              const ISoundTriggerHwCallback::PhraseRecognitionEvent& event __unused,
-              int32_t cookie __unused) {
-          ALOGI("%s", __FUNCTION__);
-          return Void();
-      }
+  static void SetUpTestCase() {
+    srand(time(nullptr));
+  }
 
-      virtual Return<void> soundModelCallback(
-              const ISoundTriggerHwCallback::ModelEvent& event __unused,
-              int32_t cookie __unused) {
-          ALOGI("%s", __FUNCTION__);
-          return Void();
-      }
+  class SoundTriggerHwCallback : public ISoundTriggerHwCallback {
+   private:
+    SoundTriggerHidlTest& mParent;
+
+   public:
+    SoundTriggerHwCallback(SoundTriggerHidlTest& parent) : mParent(parent) {}
+
+    virtual Return<void> recognitionCallback(
+        const ISoundTriggerHwCallback::RecognitionEvent& event __unused,
+        int32_t cookie __unused) {
+      ALOGI("%s", __FUNCTION__);
+      return Void();
+    }
+
+    virtual Return<void> phraseRecognitionCallback(
+        const ISoundTriggerHwCallback::PhraseRecognitionEvent& event __unused,
+        int32_t cookie __unused) {
+      ALOGI("%s", __FUNCTION__);
+      return Void();
+    }
+
+    virtual Return<void> soundModelCallback(
+        const ISoundTriggerHwCallback::ModelEvent& event,
+        int32_t cookie __unused) {
+      ALOGI("%s", __FUNCTION__);
+      mParent.lastModelEvent = event;
+      mParent.monitor.notify();
+      return Void();
+    }
   };
 
   virtual void TearDown() override {}
 
+  Monitor monitor;
+  // updated by soundModelCallback()
+  ISoundTriggerHwCallback::ModelEvent lastModelEvent;
+
+ protected:
   sp<ISoundTriggerHw> mSoundTriggerHal;
-  sp<MyCallback> mCallback;
+  sp<SoundTriggerHwCallback> mCallback;
 };
 
 // A class for test environment setup (kept since this file is a template).
@@ -137,6 +203,36 @@ TEST_F(SoundTriggerHidlTest, LoadInvalidModelFail) {
 
   EXPECT_TRUE(hidlReturn.isOk());
   EXPECT_NE(0, ret);
+  EXPECT_FALSE(monitor.wait(SHORT_TIMEOUT_PERIOD));
+}
+
+/**
+ * Test ISoundTriggerHw::loadSoundModel() method
+ *
+ * Verifies that:
+ *  - the implementation returns error when passed a sound model with random data.
+ */
+TEST_F(SoundTriggerHidlTest, LoadGenericSoundModelFail) {
+  int ret = -ENODEV;
+  ISoundTriggerHw::SoundModel model;
+  SoundModelHandle handle = 0;
+
+  model.type = SoundModelType::GENERIC;
+  model.data.resize(100);
+  for (auto& d : model.data) {
+    d = rand();
+  }
+
+  Return<void> loadReturn = mSoundTriggerHal->loadSoundModel(
+      model,
+      mCallback, 0, [&](int32_t retval, auto res) {
+    ret = retval;
+    handle = res;
+  });
+
+  EXPECT_TRUE(loadReturn.isOk());
+  EXPECT_NE(0, ret);
+  EXPECT_FALSE(monitor.wait(SHORT_TIMEOUT_PERIOD));
 }
 
 /**