Publishing R3
[platform/upstream/dldt.git] / inference-engine / tests / unit / inference_engine_tests / blob_proxy_test.cpp
1 // Copyright (C) 2018 Intel Corporation
2 //
3 // SPDX-License-Identifier: Apache-2.0
4 //
5
6 #include <gtest/gtest.h>
7 #include <gmock/gmock-spec-builders.h>
8
9 #include "mock_allocator.hpp"
10 #include <ie_blob.h>
11 #include <ie_blob_proxy.hpp>
12
13 using namespace ::testing;
14 using namespace std;
15 using namespace InferenceEngine;
16 using namespace InferenceEngine::details;
17
18 #define MAKE_SHORT(l, h) h * 0x100 + l
19
20 class BlobProxyTests: public ::testing::Test {
21 protected:
22     virtual void TearDown() {
23     }
24
25     virtual void SetUp() {
26     }
27
28     shared_ptr<MockAllocator> createMockAllocator() {
29         return shared_ptr<MockAllocator>(new MockAllocator());
30     }
31
32
33 public:
34
35 };
36
37 TEST_F(BlobProxyTests, convertByteBlobToFloat) {
38     const int size = 4;
39     float test_array[size] = {2.2f, 3.5f, 1.1f, 0.0f};
40     TBlob<uint8_t>::Ptr b(new TBlob<uint8_t>(Precision::U8, C, {size * sizeof(float)}));
41     b->allocate();
42     uint8_t *sPtr = (uint8_t *) test_array;
43     uint8_t *dPtr = b->data();
44     ASSERT_EQ(b->size(), size * sizeof(float));
45     for (size_t i = 0; i < b->size(); i++) {
46         dPtr[i] = sPtr[i];
47     }
48 }
49
50 TEST_F(BlobProxyTests, shouldThrowOnAllocate) {
51     SizeVector v = {1, 2, 3};
52     auto allocator = createMockAllocator();
53
54     TBlobProxy<float> proxy(Precision::FP32, C, TBlob<float>(Precision::FP32, CHW, v, dynamic_pointer_cast<IAllocator>(allocator)), 2, {2});
55
56     EXPECT_THROW(((Blob&)proxy).allocate(), InferenceEngineException);
57 }
58
59 TEST_F(BlobProxyTests, shouldThrowOnDeAllocate)
60 {
61     SizeVector v = {1, 2, 3};
62     auto allocator = createMockAllocator();
63
64     TBlobProxy<float> proxy(Precision::FP32, C, TBlob<float>(Precision::FP32, CHW, v, dynamic_pointer_cast<IAllocator>(allocator)), 2, {2});
65
66     EXPECT_THROW(((Blob&)proxy).deallocate(), InferenceEngineException);
67 }
68
69
70 TEST_F(BlobProxyTests, canAccessProxyBlobUsingBaseMethod)
71 {
72     SizeVector v = {1, 2, 3};
73     auto allocator = createMockAllocator();
74
75     float data[] = {5,6,7,8,9,10};
76
77     EXPECT_CALL(*allocator.get(), alloc(1 * 2 * 3 * sizeof(float))).WillRepeatedly(Return((void*)1));
78     EXPECT_CALL(*allocator.get(), lock(_,LOCK_FOR_WRITE)).WillRepeatedly(Return(data));
79     EXPECT_CALL(*allocator.get(), unlock(_)).Times(1);
80     EXPECT_CALL(*allocator.get(), free(_)).Times(1);
81
82     TBlob<float> blob(Precision::FP32, CHW, v, dynamic_pointer_cast<IAllocator>(allocator));
83     blob.allocate();
84
85     TBlobProxy<float> proxy(Precision::FP32, C, move(blob), 2, {2});
86
87     auto proxyBuffer = proxy.buffer();
88     float *ptr = (float*)(void*)proxyBuffer;
89     ASSERT_EQ(ptr[2] , 9);
90 }
91
92 TEST_F(BlobProxyTests, canAccessProxyBlobUsingHelpers)
93 {
94     SizeVector v = {1, 2, 3};
95     auto allocator = createMockAllocator();
96
97     float data[] = {5,6,7, 8, 9, 10};
98
99     EXPECT_CALL(*allocator.get(), alloc(1 * 2 * 3 * sizeof(float))).WillRepeatedly(Return((void*)1));
100     EXPECT_CALL(*allocator.get(), lock(_,LOCK_FOR_WRITE)).WillOnce(Return(data));
101     EXPECT_CALL(*allocator.get(), lock(_,LOCK_FOR_READ)).WillOnce(Return(data));
102     EXPECT_CALL(*allocator.get(), unlock(_)).Times(2);
103     EXPECT_CALL(*allocator.get(), free(_)).Times(1);
104
105     TBlob<float> blob(Precision::FP32, CHW, v, dynamic_pointer_cast<IAllocator>(allocator));
106     blob.allocate();
107
108     TBlobProxy<float> proxy(Precision::FP32, C, std::move(blob), 2, {2});
109
110     auto proxyData = proxy.data();
111     float *ptr = (float * )&proxyData[0];
112     ASSERT_EQ(ptr[2] , 9);
113
114     auto readOnly = proxy.readOnly();
115     ptr = (float * )&readOnly[0];
116     ASSERT_EQ(ptr[2] , 9);
117 }
118
119 TEST_F(BlobProxyTests, canCreateProxyBlobFromDifferentBaseBlobType)
120 {
121     SizeVector v = {1, 2, 3};
122     auto allocator = createMockAllocator();
123
124     uint8_t data[] = {5, 6, 7, 8, 9, 10};
125
126     EXPECT_CALL(*allocator.get(), alloc(1 * 2 * 3 * sizeof(uint8_t))).WillRepeatedly(Return((void*)1));
127     EXPECT_CALL(*allocator.get(), lock(_,LOCK_FOR_READ)).WillOnce(Return(data));
128     EXPECT_CALL(*allocator.get(), unlock(_)).Times(1);
129     EXPECT_CALL(*allocator.get(), free(_)).Times(1);
130
131     TBlob<uint8_t > blob(Precision::U8, CHW, v, dynamic_pointer_cast<IAllocator>(allocator));
132     blob.allocate();
133
134     Blob::Ptr spBlob (&blob, [](Blob*){
135         //don't delete
136     });
137
138     TBlobProxy<short> proxy(Precision::I16, C, spBlob, 0, {3});
139
140     auto readOnly = proxy.readOnly();
141     const short * ptr = readOnly;
142     ASSERT_EQ(ptr[0] , MAKE_SHORT(data[0], data[1]));
143     ASSERT_EQ(ptr[1] , MAKE_SHORT(data[2], data[3]));
144     ASSERT_EQ(ptr[2] , MAKE_SHORT(data[4], data[5]));
145 }
146
147 TEST_F(BlobProxyTests, canNotCreateBlobWithOffsetOfSizeOutOfOriginal) {
148     SizeVector v = {1, 1, 3};
149     auto allocator = createMockAllocator();
150
151     EXPECT_CALL(*allocator.get(), alloc(1 * 1 * 3 * sizeof(float))).WillRepeatedly(Return((void*)1));
152     EXPECT_CALL(*allocator.get(), free(_)).Times(1);
153
154     TBlob<float> blob(Precision::FP32, CHW, v, dynamic_pointer_cast<IAllocator>(allocator));
155     blob.allocate();
156
157     Blob::Ptr spBlob (&blob, [](Blob*){
158         //don't delete
159     });
160
161     EXPECT_THROW(TBlobProxy<float>(Precision::FP32, C, spBlob, 0, {4}), InferenceEngineException);
162     EXPECT_THROW(TBlobProxy<float>(Precision::FP32, C, spBlob, 3, {1}), InferenceEngineException);
163     EXPECT_THROW(TBlobProxy<float>(Precision::FP32, C, spBlob, 2, {2}), InferenceEngineException);
164 }
165
166
167 TEST_F(BlobProxyTests, canAccessBothArraysAfterProxying)
168 {
169     SizeVector v = {1, 2, 4};
170     auto allocator = createMockAllocator();
171
172     uint8_t data[] = {5, 6, 7, 8, 9, 10, 11, 12};
173
174     EXPECT_CALL(*allocator.get(), alloc(1 * 2 * 4 * sizeof(uint8_t))).WillRepeatedly(Return((void*)1));
175     EXPECT_CALL(*allocator.get(), lock(_,LOCK_FOR_READ)).Times(2).WillRepeatedly(Return(data));
176     EXPECT_CALL(*allocator.get(), unlock(_)).Times(2);
177     EXPECT_CALL(*allocator.get(), free(_)).Times(1);
178
179     TBlob<uint8_t> blob(Precision::U8, CHW, v, dynamic_pointer_cast<IAllocator>(allocator));
180     blob.allocate();
181
182     Blob::Ptr spBlob (&blob, [](Blob*){
183         //don't delete
184     });
185
186     TBlobProxy<short> proxy(Precision::I16, C, spBlob, 2, {3});
187
188     auto readOnly = proxy.readOnly();
189     short * ptr = (short * )&readOnly[0];
190     ASSERT_EQ(ptr[0] , MAKE_SHORT(data[2], data[3]));
191     ASSERT_EQ(ptr[1] , MAKE_SHORT(data[4], data[5]));
192
193     auto origBuffer = blob.readOnly();
194     const uint8_t* origPtr = origBuffer;
195
196     ASSERT_EQ(origPtr[0] , 5);
197     ASSERT_EQ(origPtr[1] , 6);
198
199 }
200
201 TEST_F(BlobProxyTests, convertTwoByteBlobToFloat) {
202     const int size = 4;
203     float test_array[size] = {2.2f, 3.5f, 1.1f, 0.0f};
204     TBlob<uint16_t>::Ptr b(new TBlob<uint16_t>(Precision::U16, C, {size*sizeof(float) / sizeof(uint16_t)}));
205     b->allocate();
206     uint16_t *sPtr = (uint16_t *) test_array;
207     uint16_t *dPtr = b->data();
208     ASSERT_EQ(b->byteSize(), size*sizeof(float));
209     ASSERT_EQ(b->size(), size*sizeof(float)/sizeof(uint16_t));
210     for(size_t i = 0; i < b->size(); i++) {
211         dPtr[i] = sPtr[i];
212     }
213
214     TBlobProxy<float>::Ptr proxy(new TBlobProxy<float>(Precision::FP32, C, b, sizeof(float) / sizeof(uint16_t), {size - 1}));
215     ASSERT_NEAR(3.5f, proxy->data()[0], 0.0001f);
216     ASSERT_NEAR(1.1f, proxy->data()[1], 0.0001f);
217     ASSERT_NEAR(0.0f, proxy->data()[2], 0.0001f);
218     ASSERT_EQ(size - 1, proxy->size());
219     ASSERT_EQ(size*sizeof(float) - sizeof(float), proxy->byteSize());
220 }
221
222 TEST_F(BlobProxyTests, throwsIfSmallProxyObjectSize) {
223     TBlob<float>::Ptr b(new TBlob<float>(Precision::FP32, C));
224     b->set({ 1.0f, 2.0f, 3.0f });
225     try {
226         TBlobProxy<uint8_t> proxy(Precision::U8, C, b, 0, { b->byteSize() + 1 });
227         FAIL() << "Should have failed by now: proxy size is larger than blob size";
228     }
229     catch (InferenceEngine::details::InferenceEngineException ex) {};
230 }
231
232 TEST_F(BlobProxyTests, canReturnConstantData) {
233     TBlob<float>::Ptr b(new TBlob<float>(Precision::FP32, C));
234     b->set({ 1.0f, 2.0f, 3.0f });
235     TBlobProxy<uint8_t> const proxy(Precision::U8, C, b, 0, { b->byteSize() });
236     ASSERT_NE(proxy.cbuffer().as<const void*>(), nullptr);
237 }
238
239 TEST_F(BlobProxyTests, noAllocDeallocLogic) {
240     TBlob<float>::Ptr b(new TBlob<float>(Precision::FP32, C));
241     b->set({ 1.0f, 2.0f, 3.0f });
242     TBlobProxy<uint8_t> proxy(Precision::U8, C, b, 0, { b->byteSize() });
243     ASSERT_ANY_THROW(((Blob*) &proxy)->allocate());
244     ASSERT_ANY_THROW(((Blob*) &proxy)->deallocate());
245 }
246
247
248 TEST_F(BlobProxyTests, canIterateOverData) {
249     TBlob<uint8_t>::Ptr b(new TBlob<uint8_t >(Precision::FP32, C));
250     b->set({ 1, 2, 3 });
251     TBlobProxy<uint8_t> proxy(Precision::U8, C, b, 1, { 2 });
252     vector<uint8_t > u8buffer;
253     for (auto & element : proxy) {
254         u8buffer.push_back(element);
255     }
256     ASSERT_EQ(2, u8buffer.size());
257     ASSERT_EQ(2, u8buffer[0]);
258     ASSERT_EQ(3, u8buffer[1]);
259 }
260
261 TEST_F(BlobProxyTests, canIterateOverReadOnly) {
262     TBlob<uint8_t>::Ptr b(new TBlob<uint8_t >(Precision::FP32, C));
263     b->set({ 1, 2, 3 });
264     TBlobProxy<uint8_t> const proxy(Precision::U8, C, b, 1, { 2 });
265     vector<uint8_t > u8buffer;
266     for (auto  element : proxy) {
267         u8buffer.push_back(element);
268     }
269     ASSERT_EQ(2, u8buffer.size());
270     ASSERT_EQ(2, u8buffer[0]);
271     ASSERT_EQ(3, u8buffer[1]);
272 }