IVGCVSW-4917 Adding Unit test to Android-nn-driver for Hal1.3 Qos

Signed-off-by: David Monahan <david.monahan@arm.com>
Change-Id: Ie45464f2b04c8f2bb30ca06ff91b96492f2466b0
diff --git a/test/1.3/QosTests.cpp b/test/1.3/QosTests.cpp
new file mode 100644
index 0000000..d51152b
--- /dev/null
+++ b/test/1.3/QosTests.cpp
@@ -0,0 +1,192 @@
+//
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "../DriverTestHelpers.hpp"
+#include "../TestTensor.hpp"
+
+#include "../1.3/HalPolicy.hpp"
+
+#include <armnn/utility/IgnoreUnused.hpp>
+
+#include <boost/test/unit_test.hpp>
+#include <boost/test/data/test_case.hpp>
+
+
+BOOST_AUTO_TEST_SUITE(QosTests)
+
+using ArmnnDriver   = armnn_driver::ArmnnDriver;
+using DriverOptions = armnn_driver::DriverOptions;
+
+using namespace android::nn;
+using namespace android::hardware;
+using namespace driverTestHelpers;
+using namespace armnn_driver;
+
+using HalPolicy = hal_1_3::HalPolicy;
+
+namespace
+{
+
+void ExecuteModel(const armnn_driver::hal_1_3::HalPolicy::Model& model,
+                  armnn_driver::ArmnnDriver& driver,
+                  const V1_0::Request& request)
+{
+    android::sp<V1_3::IPreparedModel> preparedModel = PrepareModel_1_3(model, driver);
+    if (preparedModel.get() != nullptr)
+    {
+        Execute(preparedModel, request);
+    }
+}
+
+#ifndef ARMCOMPUTECL_ENABLED
+static const std::array<armnn::Compute, 1> COMPUTE_DEVICES = {{ armnn::Compute::CpuRef }};
+#else
+static const std::array<armnn::Compute, 2> COMPUTE_DEVICES = {{ armnn::Compute::CpuRef, armnn::Compute::CpuAcc }};
+#endif
+
+BOOST_AUTO_TEST_CASE(ConcurrentExecuteWithQosPriority)
+{
+    ALOGI("ConcurrentExecuteWithQOSPriority: entry");
+
+    auto driver = std::make_unique<ArmnnDriver>(DriverOptions(armnn::Compute::CpuRef));
+    HalPolicy::Model model = {};
+
+    // add operands
+    int32_t actValue      = 0;
+    float   weightValue[] = {2, 4, 1};
+    float   biasValue[]   = {4};
+
+    AddInputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 3});
+    AddTensorOperand<HalPolicy>(model,
+                      hidl_vec<uint32_t>{1, 3},
+                      weightValue,
+                      HalPolicy::OperandType::TENSOR_FLOAT32,
+                      V1_3::OperandLifeTime::CONSTANT_COPY);
+    AddTensorOperand<HalPolicy>(model,
+                      hidl_vec<uint32_t>{1},
+                      biasValue,
+                      HalPolicy::OperandType::TENSOR_FLOAT32,
+                      V1_3::OperandLifeTime::CONSTANT_COPY);
+    AddIntOperand<HalPolicy>(model, actValue);
+    AddOutputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 1});
+
+    // make the fully connected operation
+    model.main.operations.resize(1);
+    model.main.operations[0].type    = HalPolicy::OperationType::FULLY_CONNECTED;
+    model.main.operations[0].inputs  = hidl_vec<uint32_t>{0, 1, 2, 3};
+    model.main.operations[0].outputs = hidl_vec<uint32_t>{4};
+
+    // make the prepared models
+    const size_t maxRequests = 45;
+    size_t preparedModelsSize = 0;
+    android::sp<V1_3::IPreparedModel> preparedModels[maxRequests];
+    V1_3::ErrorStatus status(V1_3::ErrorStatus::NONE);
+    size_t start = preparedModelsSize;
+    for (size_t i = start; i < start+15; ++i)
+    {
+        preparedModels[i] = PrepareModelWithStatus_1_3(model, *driver, status, V1_3::Priority::LOW);
+        preparedModelsSize++;
+    }
+    start = preparedModelsSize;
+    for (size_t i = start; i < start+15; ++i)
+    {
+        preparedModels[i] = PrepareModelWithStatus_1_3(model, *driver, status, V1_3::Priority::MEDIUM);
+        preparedModelsSize++;
+    }
+    start = preparedModelsSize;
+    for (size_t i = start; i < start+15; ++i)
+    {
+        preparedModels[i] = PrepareModelWithStatus_1_3(model, *driver, status, V1_3::Priority::HIGH);
+        preparedModelsSize++;
+    }
+
+    BOOST_TEST(maxRequests == preparedModelsSize);
+
+    // construct the request data
+    DataLocation inloc = {};
+    inloc.poolIndex = 0;
+    inloc.offset    = 0;
+    inloc.length    = 3 * sizeof(float);
+    RequestArgument input = {};
+    input.location = inloc;
+    input.dimensions = hidl_vec<uint32_t>{};
+
+    DataLocation outloc = {};
+    outloc.poolIndex = 1;
+    outloc.offset    = 0;
+    outloc.length    = 1 * sizeof(float);
+    RequestArgument output = {};
+    output.location  = outloc;
+    output.dimensions = hidl_vec<uint32_t>{};
+
+    // build the requests
+    V1_0::Request requests[maxRequests];
+    android::sp<IMemory> outMemory[maxRequests];
+    float* outdata[maxRequests];
+    for (size_t i = 0; i < maxRequests; ++i)
+    {
+        requests[i].inputs  = hidl_vec<RequestArgument>{input};
+        requests[i].outputs = hidl_vec<RequestArgument>{output};
+        // set the input data (matching source test)
+        float inDataLow[] = {2, 32, 16};
+        float inDataMedium[] = {1, 31, 11};
+        float inDataHigh[] = {3, 33, 17};
+        if (i < 15)
+        {
+            AddPoolAndSetData<float>(3, requests[i], inDataLow);
+        }
+        else if (i < 30)
+        {
+            AddPoolAndSetData<float>(3, requests[i], inDataMedium);
+        }
+        else
+        {
+            AddPoolAndSetData<float>(3, requests[i], inDataHigh);
+        }
+        // add memory for the output
+        outMemory[i] = AddPoolAndGetData<float>(1, requests[i]);
+        outdata[i] = static_cast<float*>(static_cast<void*>(outMemory[i]->getPointer()));
+    }
+
+    // invoke the execution of the requests
+    ALOGI("ConcurrentExecuteWithQOSPriority: executing requests");
+    android::sp<ExecutionCallback> cb[maxRequests];
+    for (size_t i = 0; i < maxRequests; ++i)
+    {
+        cb[i] = ExecuteNoWait(preparedModels[i], requests[i]);
+    }
+
+    // wait for the requests to complete
+    ALOGI("ConcurrentExecuteWithQOSPriority: waiting for callbacks");
+    for (size_t i = 0; i < maxRequests; ++i)
+    {
+        ARMNN_ASSERT(cb[i]);
+        cb[i]->wait();
+    }
+
+    // check the results
+    ALOGI("ConcurrentExecuteWithQOSPriority: validating results");
+    for (size_t i = 0; i < maxRequests; ++i)
+    {
+        if (i < 15)
+        {
+            BOOST_TEST(outdata[i][0] == 152);
+        }
+        else if (i < 30)
+        {
+            BOOST_TEST(outdata[i][0] == 141);
+        }
+        else
+        {
+            BOOST_TEST(outdata[i][0] == 159);
+        }
+
+    }
+    ALOGI("ConcurrentExecuteWithQOSPriority: exit");
+}
+
+} // anonymous namespace
+
+BOOST_AUTO_TEST_SUITE_END()
\ No newline at end of file