IVGCVSW-5036 Do not allocate memory when import is enabled

Signed-off-by: Narumol Prangnawarat <narumol.prangnawarat@arm.com>
Change-Id: Ideaae5280702aae6c73f3b4e4cee9f71a8386fda
diff --git a/src/backends/reference/test/RefTensorHandleTests.cpp b/src/backends/reference/test/RefTensorHandleTests.cpp
index be229bf..42f5664 100644
--- a/src/backends/reference/test/RefTensorHandleTests.cpp
+++ b/src/backends/reference/test/RefTensorHandleTests.cpp
@@ -3,6 +3,7 @@
 // SPDX-License-Identifier: MIT
 //
 #include <reference/RefTensorHandle.hpp>
+#include <reference/RefTensorHandleFactory.hpp>
 
 #include <boost/test/unit_test.hpp>
 
@@ -13,7 +14,7 @@
 {
     std::shared_ptr<RefMemoryManager> memoryManager = std::make_shared<RefMemoryManager>();
 
-    TensorInfo info({1,1,1,1}, DataType::Float32);
+    TensorInfo info({ 1, 1, 1, 1 }, DataType::Float32);
     RefTensorHandle handle(info, memoryManager);
 
     handle.Manage();
@@ -21,7 +22,7 @@
 
     memoryManager->Acquire();
     {
-        float *buffer = reinterpret_cast<float *>(handle.Map());
+        float* buffer = reinterpret_cast<float*>(handle.Map());
 
         BOOST_CHECK(buffer != nullptr); // Yields a valid pointer
 
@@ -34,7 +35,7 @@
 
     memoryManager->Acquire();
     {
-        float *buffer = reinterpret_cast<float *>(handle.Map());
+        float* buffer = reinterpret_cast<float*>(handle.Map());
 
         BOOST_CHECK(buffer != nullptr); // Yields a valid pointer
 
@@ -45,14 +46,107 @@
     memoryManager->Release();
 }
 
+BOOST_AUTO_TEST_CASE(RefTensorHandleFactoryMemoryManaged)
+{
+    std::shared_ptr<RefMemoryManager> memoryManager = std::make_shared<RefMemoryManager>();
+    RefTensorHandleFactory handleFactory(memoryManager);
+    TensorInfo info({ 1, 1, 2, 1 }, DataType::Float32);
+
+    // create TensorHandle with memory managed
+    auto handle = handleFactory.CreateTensorHandle(info, true);
+    handle->Manage();
+    handle->Allocate();
+
+    memoryManager->Acquire();
+    {
+        float* buffer = reinterpret_cast<float*>(handle->Map());
+        BOOST_CHECK(buffer != nullptr); // Yields a valid pointer
+        buffer[0] = 1.5f;
+        buffer[1] = 2.5f;
+        BOOST_CHECK(buffer[0] == 1.5f); // Memory is writable and readable
+        BOOST_CHECK(buffer[1] == 2.5f); // Memory is writable and readable
+    }
+    memoryManager->Release();
+
+    memoryManager->Acquire();
+    {
+        float* buffer = reinterpret_cast<float*>(handle->Map());
+        BOOST_CHECK(buffer != nullptr); // Yields a valid pointer
+        buffer[0] = 3.5f;
+        buffer[1] = 4.5f;
+        BOOST_CHECK(buffer[0] == 3.5f); // Memory is writable and readable
+        BOOST_CHECK(buffer[1] == 4.5f); // Memory is writable and readable
+    }
+    memoryManager->Release();
+
+    float testPtr[2] = { 2.5f, 5.5f };
+    // Cannot import as import is disabled
+    BOOST_CHECK(!handle->Import(static_cast<void*>(testPtr), MemorySource::Malloc));
+}
+
+BOOST_AUTO_TEST_CASE(RefTensorHandleFactoryImport)
+{
+    std::shared_ptr<RefMemoryManager> memoryManager = std::make_shared<RefMemoryManager>();
+    RefTensorHandleFactory handleFactory(memoryManager);
+    TensorInfo info({ 1, 1, 2, 1 }, DataType::Float32);
+
+    // create TensorHandle without memory managed
+    auto handle = handleFactory.CreateTensorHandle(info, false);
+    handle->Manage();
+    handle->Allocate();
+    memoryManager->Acquire();
+
+    // No buffer allocated when import is enabled
+    BOOST_CHECK_THROW(handle->Map(), armnn::NullPointerException);
+
+    float testPtr[2] = { 2.5f, 5.5f };
+    // Correctly import
+    BOOST_CHECK(handle->Import(static_cast<void*>(testPtr), MemorySource::Malloc));
+    float* buffer = reinterpret_cast<float*>(handle->Map());
+    BOOST_CHECK(buffer != nullptr); // Yields a valid pointer after import
+    BOOST_CHECK(buffer == testPtr); // buffer is pointing to testPtr
+    // Memory is writable and readable with correct value
+    BOOST_CHECK(buffer[0] == 2.5f);
+    BOOST_CHECK(buffer[1] == 5.5f);
+    buffer[0] = 3.5f;
+    buffer[1] = 10.0f;
+    BOOST_CHECK(buffer[0] == 3.5f);
+    BOOST_CHECK(buffer[1] == 10.0f);
+    memoryManager->Release();
+}
+
+BOOST_AUTO_TEST_CASE(RefTensorHandleImport)
+{
+    TensorInfo info({ 1, 1, 2, 1 }, DataType::Float32);
+    RefTensorHandle handle(info, static_cast<unsigned int>(MemorySource::Malloc));
+
+    handle.Manage();
+    handle.Allocate();
+
+    // No buffer allocated when import is enabled
+    BOOST_CHECK_THROW(handle.Map(), armnn::NullPointerException);
+
+    float testPtr[2] = { 2.5f, 5.5f };
+    // Correctly import
+    BOOST_CHECK(handle.Import(static_cast<void*>(testPtr), MemorySource::Malloc));
+    float* buffer = reinterpret_cast<float*>(handle.Map());
+    BOOST_CHECK(buffer != nullptr); // Yields a valid pointer after import
+    BOOST_CHECK(buffer == testPtr); // buffer is pointing to testPtr
+    // Memory is writable and readable with correct value
+    BOOST_CHECK(buffer[0] == 2.5f);
+    BOOST_CHECK(buffer[1] == 5.5f);
+    buffer[0] = 3.5f;
+    buffer[1] = 10.0f;
+    BOOST_CHECK(buffer[0] == 3.5f);
+    BOOST_CHECK(buffer[1] == 10.0f);
+}
+
 #if !defined(__ANDROID__)
 // Only run these tests on non Android platforms
 BOOST_AUTO_TEST_CASE(CheckSourceType)
 {
-    std::shared_ptr<RefMemoryManager> memoryManager = std::make_shared<RefMemoryManager>();
-
     TensorInfo info({1}, DataType::Float32);
-    RefTensorHandle handle(info, memoryManager, static_cast<unsigned int>(MemorySource::Malloc));
+    RefTensorHandle handle(info, static_cast<unsigned int>(MemorySource::Malloc));
 
     int* testPtr = new int(4);
 
@@ -70,10 +164,8 @@
 
 BOOST_AUTO_TEST_CASE(ReusePointer)
 {
-    std::shared_ptr<RefMemoryManager> memoryManager = std::make_shared<RefMemoryManager>();
-
     TensorInfo info({1}, DataType::Float32);
-    RefTensorHandle handle(info, memoryManager, static_cast<unsigned int>(MemorySource::Malloc));
+    RefTensorHandle handle(info, static_cast<unsigned int>(MemorySource::Malloc));
 
     int* testPtr = new int(4);
 
@@ -87,10 +179,8 @@
 
 BOOST_AUTO_TEST_CASE(MisalignedPointer)
 {
-    std::shared_ptr<RefMemoryManager> memoryManager = std::make_shared<RefMemoryManager>();
-
     TensorInfo info({2}, DataType::Float32);
-    RefTensorHandle handle(info, memoryManager, static_cast<unsigned int>(MemorySource::Malloc));
+    RefTensorHandle handle(info, static_cast<unsigned int>(MemorySource::Malloc));
 
     // Allocate a 2 int array
     int* testPtr = new int[2];