Home | History | Annotate | Download | only in component
      1 /*
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_NDEBUG 0
     18 #define LOG_TAG "codec2_hidl_hal_component_test"
     19 
     20 #include <android-base/logging.h>
     21 #include <gtest/gtest.h>
     22 
     23 #include <hardware/google/media/c2/1.0/IComponent.h>
     24 #include <hardware/google/media/c2/1.0/IComponentStore.h>
     25 
     26 using ::hardware::google::media::c2::V1_0::IComponent;
     27 using ::hardware::google::media::c2::V1_0::IComponentStore;
     28 using ::hardware::google::media::c2::V1_0::IComponentInterface;
     29 using ::hardware::google::media::c2::V1_0::FieldSupportedValuesQuery;
     30 using ::hardware::google::media::c2::V1_0::FieldSupportedValuesQueryResult;
     31 using ::hardware::google::media::c2::V1_0::ParamDescriptor;
     32 using ::hardware::google::media::c2::V1_0::SettingResult;
     33 using ::android::hardware::hidl_vec;
     34 using ::android::hardware::hidl_string;
     35 using ::android::sp;
     36 
     37 #include <VtsHalHidlTargetTestBase.h>
     38 #include "media_c2_hidl_test_common.h"
     39 
     40 static ComponentTestEnvironment* gEnv = nullptr;
     41 
     42 namespace {
     43 
     44 // google.codec2 Component test setup
     45 class Codec2ComponentHalTest : public ::testing::VtsHalHidlTargetTestBase {
     46    private:
     47     typedef ::testing::VtsHalHidlTargetTestBase Super;
     48 
     49    public:
     50     virtual void SetUp() override {
     51         Super::SetUp();
     52         mStore = Super::getService<IComponentStore>(gEnv->getInstance());
     53         ASSERT_NE(mStore, nullptr);
     54         mListener = new CodecListener();
     55         ASSERT_NE(mListener, nullptr);
     56         mStore->createComponent(gEnv->getComponent().c_str(), mListener,
     57                                 nullptr,
     58                                 [&](Status _s, const sp<IComponent>& _nl) {
     59                                     ASSERT_EQ(_s, Status::OK);
     60                                     this->mComponent = _nl;
     61                                 });
     62         ASSERT_NE(mComponent, nullptr);
     63     }
     64 
     65     virtual void TearDown() override {
     66         if (mComponent != nullptr) {
     67             // If you have encountered a fatal failure, it is possible that
     68             // freeNode() will not go through. Instead of hanging the app.
     69             // let it pass through and report errors
     70             if (::testing::Test::HasFatalFailure()) return;
     71             mComponent->release();
     72             mComponent = nullptr;
     73         }
     74         Super::TearDown();
     75     }
     76 
     77     sp<IComponent> mComponent;
     78     sp<IComponentStore> mStore;
     79     sp<CodecListener> mListener;
     80 
     81    protected:
     82     static void description(const std::string& description) {
     83         RecordProperty("description", description);
     84     }
     85 };
     86 
     87 // Test Empty Flush
     88 TEST_F(Codec2ComponentHalTest, EmptyFlush) {
     89     ALOGV("Empty Flush Test");
     90     Status err = mComponent->start();
     91     ASSERT_EQ(err, Status::OK);
     92 
     93     // Flushed output expected to be of 0 size, as no input has been fed
     94     mComponent->flush([&](Status _s, const WorkBundle& _flushedWorkBundle) {
     95         ASSERT_EQ(_s, Status::OK);
     96         ASSERT_EQ(_flushedWorkBundle.works.size(), 0u)
     97             << "Invalid Flushed Work Size";
     98         ASSERT_EQ(_flushedWorkBundle.baseBlocks.size(), 0u);
     99     });
    100 }
    101 
    102 // Test Queue Empty Work
    103 TEST_F(Codec2ComponentHalTest, QueueEmptyWork) {
    104     ALOGV("Queue Empty Work Test");
    105     Status err = mComponent->start();
    106     ASSERT_EQ(err, Status::OK);
    107 
    108     // Queueing an empty WorkBundle
    109     const WorkBundle workBundle = {};
    110     err = mComponent->queue(workBundle);
    111     ASSERT_EQ(err, Status::OK);
    112 
    113     err = mComponent->reset();
    114     ASSERT_EQ(err, Status::OK);
    115 }
    116 
    117 // Test Component Configuration
    118 TEST_F(Codec2ComponentHalTest, Config) {
    119     ALOGV("Configuration Test");
    120     mComponent->getName([](const hidl_string& name) {
    121         EXPECT_NE(name.empty(), true) << "Invalid Component Store Name";
    122         ALOGV("Component under Test %s", name.c_str());
    123     });
    124 
    125 #define MAX_PARAMS 64
    126     /* Querry Supported Params */
    127     hidl_vec<ParamDescriptor> params;
    128     mComponent->querySupportedParams(
    129         0, MAX_PARAMS,
    130         [&params](Status _s, const hidl_vec<ParamDescriptor>& _p) {
    131             ASSERT_EQ(_s, Status::OK);
    132             params = _p;
    133             ALOGE("TEMP - Params capacity - %zu", _p.size());
    134         });
    135 
    136     std::vector<uint32_t> tempIndices;
    137     std::vector<FieldSupportedValuesQuery> tempInFields;
    138     for (size_t i = 0; i < params.size(); i++) {
    139         EXPECT_NE(params[i].name.empty(), true)
    140             << "Invalid Supported Param Name";
    141         ALOGV("Params Supported : %s", params[i].name.c_str());
    142         tempIndices.push_back(params[i].index);
    143         FieldSupportedValuesQuery tempFSV;
    144         tempFSV.field.index = params[i].index;
    145         tempInFields.push_back(tempFSV);
    146     }
    147 
    148 
    149     /* Query Supported Values */
    150     const hidl_vec<FieldSupportedValuesQuery> inFields = tempInFields;
    151     bool mayBlock = false;
    152     hidl_vec<FieldSupportedValuesQueryResult> outFields;
    153     mComponent->querySupportedValues(
    154         inFields, mayBlock,
    155         [&outFields](
    156             Status _s,
    157             const hidl_vec<FieldSupportedValuesQueryResult>& _outFields) {
    158             ASSERT_EQ(_s, Status::OK);
    159             outFields = _outFields;
    160         });
    161 
    162     // Fileds size should match
    163     ASSERT_EQ(inFields.size(), outFields.size());
    164 
    165     /* TODO: How to give proper indices */
    166     const hidl_vec<uint32_t> indices = tempIndices;
    167     hidl_vec<uint8_t> inParamsQuery;
    168     mComponent->query(indices, mayBlock,
    169                       [&inParamsQuery](Status _s, const hidl_vec<uint8_t>& _p) {
    170                           ASSERT_EQ(_s, Status::OK);
    171                           inParamsQuery = _p;
    172                       });
    173 
    174     /* Config default parameters*/
    175     const hidl_vec<uint8_t> inParams = inParamsQuery;
    176     hidl_vec<uint8_t> outParamsQuery;
    177     mComponent->config(
    178         inParams, mayBlock,
    179         [&outParamsQuery](Status _s, const hidl_vec<SettingResult>& _f,
    180                           const hidl_vec<uint8_t>& _outParams) {
    181             ASSERT_EQ(_s, Status::OK);
    182             // There should be no failures, since default config is reapplied
    183             ASSERT_EQ(_f.size(), 0u);
    184             outParamsQuery = _outParams;
    185         });
    186 
    187     // Fileds size should match
    188     ASSERT_EQ(inParams.size(), outParamsQuery.size());
    189 }
    190 
    191 // Test Multiple Start Stop Reset Test
    192 TEST_F(Codec2ComponentHalTest, MultipleStartStopReset) {
    193     ALOGV("Multiple Start Stop and Reset Test");
    194     Status err = Status::OK;
    195 
    196 #define MAX_RETRY 16
    197 
    198     for (size_t i = 0; i < MAX_RETRY; i++) {
    199         err = mComponent->start();
    200         ASSERT_EQ(err, Status::OK);
    201 
    202         err = mComponent->stop();
    203         ASSERT_EQ(err, Status::OK);
    204     }
    205 
    206     err = mComponent->start();
    207     ASSERT_EQ(err, Status::OK);
    208 
    209     for (size_t i = 0; i < MAX_RETRY; i++) {
    210         err = mComponent->reset();
    211         ASSERT_EQ(err, Status::OK);
    212     }
    213 
    214     err = mComponent->start();
    215     ASSERT_EQ(err, Status::OK);
    216 
    217     err = mComponent->stop();
    218     ASSERT_EQ(err, Status::OK);
    219 
    220     // Second stop should return error
    221     err = mComponent->stop();
    222     ASSERT_NE(err, Status::OK);
    223 }
    224 
    225 }  // anonymous namespace
    226 
    227 // TODO: Add test for Invalid work, Invalid Config handling
    228 // TODO: Add test for Invalid states
    229 int main(int argc, char** argv) {
    230     gEnv = new ComponentTestEnvironment();
    231     ::testing::AddGlobalTestEnvironment(gEnv);
    232     ::testing::InitGoogleTest(&argc, argv);
    233     gEnv->init(&argc, argv);
    234     int status = gEnv->initFromOptions(argc, argv);
    235     if (status == 0) {
    236         status = RUN_ALL_TESTS();
    237         LOG(INFO) << "C2 Test result = " << status;
    238     }
    239     return status;
    240 }
    241 
    242