IVGCVSW-6420: Constant flag in tensor info is not set correctly

!android-nn-driver:6532
!armnn-internal-tests:372451

  * Made fix to 2 out of 3 ConstTensor() constructors in Tensor.hpp to
    throw InvalidArgumentException when TensorInfo isConstant parameter
    is false.
  * Added new ConstTensor() constructor in Tensor.cpp to accept vector<>.data()
    using template<typename MemoryType>.
  * Fixed runtime->GetOutputTensorInfo()/GetInputTensorInfo() methods and
    called submethods to return TensorInfo& rather than TensorInfo.
  * Fixed all failing unit tests for CpuRef/CpuAcc/GpuAcc to ensure any
    ConstTensor created has it's TensorInfo isConstant set to true.
  * Added unit tests in TensorTest.cpp to ensure ConstTensor constructors
    throw InvalidArgumentException when TensorInfo isConstat parameter is
    false.
  * Added unit test to ensure an empty ConstTensor constructor will set
    TensorInfo isConatant to true.
  * Indentation fixes.
  * Fix to arm_tensor.i to add isConstant parameter to TensorInfo
    constructor. Added methods IsConstant() and SetConstant().
  * Fix to const_tensor.py to throw ValueError when TensorInfo
    isConstant is set to false when constructing a ConstTensor.
  * Fixed PyArmnn unit tests to set TensorInfo isConstant to
    True when ConstTensor is used.
  * Added unit tests in test_const_tensor.py to ensure ConstTensor
    constructors throw ValueError when TensorInfo isConstat parameter
    is false.

Signed-off-by: Cathal Corbett <cathal.corbett@arm.com>
Change-Id: I44e440dd0422c366d31bbdbc77ad2b4db0bde148
diff --git a/python/pyarmnn/test/test_const_tensor.py b/python/pyarmnn/test/test_const_tensor.py
index fa6327f..2358d65 100644
--- a/python/pyarmnn/test/test_const_tensor.py
+++ b/python/pyarmnn/test/test_const_tensor.py
@@ -6,8 +6,8 @@
 import pyarmnn as ann
 
 
-def _get_tensor_info(dt):
-    tensor_info = ann.TensorInfo(ann.TensorShape((2, 3)), dt)
+def _get_const_tensor_info(dt):
+    tensor_info = ann.TensorInfo(ann.TensorShape((2, 3)), dt, 0.0, 0, True)
 
     return tensor_info
 
@@ -23,7 +23,7 @@
                              (ann.DataType_QSymmS16, np.random.randint(1, size=(2, 4)).astype(np.int16))
                          ], ids=['float32', 'float16', 'unsigned int8', 'signed int8', 'signed int8', 'int32', 'int16'])
 def test_const_tensor_too_many_elements(dt, data):
-    tensor_info = _get_tensor_info(dt)
+    tensor_info = _get_const_tensor_info(dt)
     num_bytes = tensor_info.GetNumBytes()
 
     with pytest.raises(ValueError) as err:
@@ -43,7 +43,7 @@
                              (ann.DataType_QSymmS16, np.random.randint(1, size=(2, 2)).astype(np.int16))
                          ], ids=['float32', 'float16', 'unsigned int8', 'signed int8', 'signed int8', 'int32', 'int16'])
 def test_const_tensor_too_little_elements(dt, data):
-    tensor_info = _get_tensor_info(dt)
+    tensor_info = _get_const_tensor_info(dt)
     num_bytes = tensor_info.GetNumBytes()
 
     with pytest.raises(ValueError) as err:
@@ -63,7 +63,7 @@
                              (ann.DataType_QSymmS16, np.random.randint(1, size=(2, 2, 3, 3)).astype(np.int16))
                          ], ids=['float32', 'float16', 'unsigned int8', 'signed int8', 'signed int8', 'int32', 'int16'])
 def test_const_tensor_multi_dimensional_input(dt, data):
-    tensor = ann.ConstTensor(ann.TensorInfo(ann.TensorShape((2, 2, 3, 3)), dt), data)
+    tensor = ann.ConstTensor(ann.TensorInfo(ann.TensorShape((2, 2, 3, 3)), dt, 0.0, 0, True), data)
 
     assert data.size == tensor.GetNumElements()
     assert data.nbytes == tensor.GetNumBytes()
@@ -72,7 +72,7 @@
 
 
 def test_create_const_tensor_from_tensor():
-    tensor_info = ann.TensorInfo(ann.TensorShape((2, 3)), ann.DataType_Float32)
+    tensor_info = ann.TensorInfo(ann.TensorShape((2, 3)), ann.DataType_Float32, 0.0, 0, True)
     tensor = ann.Tensor(tensor_info)
     copied_tensor = ann.ConstTensor(tensor)
 
@@ -85,7 +85,7 @@
 
 
 def test_const_tensor_from_tensor_has_memory_area_access_after_deletion_of_original_tensor():
-    tensor_info = ann.TensorInfo(ann.TensorShape((2, 3)), ann.DataType_Float32)
+    tensor_info = ann.TensorInfo(ann.TensorShape((2, 3)), ann.DataType_Float32, 0.0, 0, True)
     tensor = ann.Tensor(tensor_info)
 
     tensor.get_memory_area()[0] = 100
@@ -125,7 +125,7 @@
                              (-1, np.random.randint(1, size=(2, 3)).astype(np.float32)),
                          ], ids=['unknown'])
 def test_const_tensor_unsupported_datatype(dt, data):
-    tensor_info = _get_tensor_info(dt)
+    tensor_info = _get_const_tensor_info(dt)
 
     with pytest.raises(ValueError) as err:
         ann.ConstTensor(tensor_info, data)
@@ -142,7 +142,7 @@
                              (ann.DataType_QSymmS8, [[1, 1, 1], [1, 1, 1]])
                          ], ids=['float32', 'float16', 'unsigned int8', 'signed int8', 'signed int8'])
 def test_const_tensor_incorrect_input_datatype(dt, data):
-    tensor_info = _get_tensor_info(dt)
+    tensor_info = _get_const_tensor_info(dt)
 
     with pytest.raises(TypeError) as err:
         ann.ConstTensor(tensor_info, data)
@@ -163,7 +163,7 @@
 class TestNumpyDataTypes:
 
     def test_copy_const_tensor(self, dt, data):
-        tensor_info = _get_tensor_info(dt)
+        tensor_info = _get_const_tensor_info(dt)
         tensor = ann.ConstTensor(tensor_info, data)
         copied_tensor = ann.ConstTensor(tensor)
 
@@ -175,7 +175,7 @@
         assert copied_tensor.GetDataType() == tensor.GetDataType()
 
     def test_const_tensor__str__(self, dt, data):
-        tensor_info = _get_tensor_info(dt)
+        tensor_info = _get_const_tensor_info(dt)
         d_type = tensor_info.GetDataType()
         num_dimensions = tensor_info.GetNumDimensions()
         num_bytes = tensor_info.GetNumBytes()
@@ -186,7 +186,7 @@
                               "{}, NumElements: {}}}".format(d_type, num_bytes, num_dimensions, num_elements)
 
     def test_const_tensor_with_info(self, dt, data):
-        tensor_info = _get_tensor_info(dt)
+        tensor_info = _get_const_tensor_info(dt)
         elements = tensor_info.GetNumElements()
         num_bytes = tensor_info.GetNumBytes()
         d_type = dt
@@ -199,7 +199,7 @@
         assert d_type == tensor.GetDataType()
 
     def test_immutable_memory(self, dt, data):
-        tensor_info = _get_tensor_info(dt)
+        tensor_info = _get_const_tensor_info(dt)
 
         tensor = ann.ConstTensor(tensor_info, data)
 
@@ -217,7 +217,7 @@
                                 ann.DataType_Signed32: np.int32,
                                 ann.DataType_Float16: np.float16}
 
-        tensor_info = _get_tensor_info(dt)
+        tensor_info = _get_const_tensor_info(dt)
         tensor = ann.ConstTensor(tensor_info, data)
         assert np_data_type_mapping[tensor.GetDataType()] == data.dtype
 
@@ -242,10 +242,34 @@
                             ann.DataType_Signed32: np.int32,
                             ann.DataType_Float16: np.float16}
 
-    tensor_info = _get_tensor_info(dt)
+    tensor_info = _get_const_tensor_info(dt)
     with pytest.raises(TypeError) as err:
         ann.ConstTensor(tensor_info, data)
 
     assert str(err.value) == "Expected data to have type {} for type {} but instead got numpy.{}".format(
         np_data_type_mapping[dt], dt, data.dtype)
 
+
+@pytest.mark.parametrize("dt, data",
+                         [
+                             (ann.DataType_Float32, np.random.randint(1, size=(2, 3)).astype(np.float32)),
+                             (ann.DataType_Float16, np.random.randint(1, size=(2, 3)).astype(np.float16)),
+                             (ann.DataType_QAsymmU8, np.random.randint(1, size=(2, 3)).astype(np.uint8)),
+                             (ann.DataType_QAsymmS8, np.random.randint(1, size=(2, 3)).astype(np.int8)),
+                             (ann.DataType_QSymmS8, np.random.randint(1, size=(2, 3)).astype(np.int8)),
+                             (ann.DataType_Signed32, np.random.randint(1, size=(2, 3)).astype(np.int32)),
+                             (ann.DataType_QSymmS16, np.random.randint(1, size=(2, 3)).astype(np.int16))
+                         ], ids=['float32', 'float16', 'unsigned int8', 'signed int8', 'signed int8', 'int32', 'int16'])
+class TestConstTensorConstructorErrors:
+
+    def test_tensorinfo_isconstant_not_set(self, dt, data):
+        with pytest.raises(ValueError) as err:
+            ann.ConstTensor(ann.TensorInfo(ann.TensorShape((2, 2, 3, 3)), dt, 0.0, 0, False), data)
+
+        assert str(err.value) == "TensorInfo when initializing ConstTensor must be set to constant."
+
+    def test_tensor_tensorinfo_isconstant_not_set(self, dt, data):
+        with pytest.raises(ValueError) as err:
+            ann.ConstTensor(ann.Tensor(ann.TensorInfo(ann.TensorShape((2, 2, 3, 3)), dt, 0.0, 0, False), data))
+
+        assert str(err.value) ==  "TensorInfo of Tensor when initializing ConstTensor must be set to constant."
\ No newline at end of file
diff --git a/python/pyarmnn/test/test_runtime.py b/python/pyarmnn/test/test_runtime.py
index fbdd804..e558e84 100644
--- a/python/pyarmnn/test/test_runtime.py
+++ b/python/pyarmnn/test/test_runtime.py
@@ -27,6 +27,7 @@
     input_tensor_id = input_binding_info[0]
 
     input_tensor_info = input_binding_info[1]
+    input_tensor_info.SetConstant()
 
     output_names = parser.GetSubgraphOutputTensorNames(graph_id)
 
diff --git a/python/pyarmnn/test/test_tensor_info.py b/python/pyarmnn/test/test_tensor_info.py
index dc73533..e54e2a9 100644
--- a/python/pyarmnn/test/test_tensor_info.py
+++ b/python/pyarmnn/test/test_tensor_info.py
@@ -21,7 +21,7 @@
 
 
 def test_tensor_info__str__():
-    tensor_info = ann.TensorInfo(ann.TensorShape((2, 3)), ann.DataType_QAsymmU8, 0.5, 1)
+    tensor_info = ann.TensorInfo(ann.TensorShape((2, 3)), ann.DataType_QAsymmU8, 0.5, 1, True)
 
     assert tensor_info.__str__() == "TensorInfo{DataType: 2, IsQuantized: 1, QuantizationScale: 0.500000, " \
-                                    "QuantizationOffset: 1, NumDimensions: 2, NumElements: 6}"
+                                    "QuantizationOffset: 1, IsConstant: 1, NumDimensions: 2, NumElements: 6}"