1 // Copyright (C) 2018 Intel Corporation
3 // SPDX-License-Identifier: Apache-2.0
6 #include <gtest/gtest.h>
7 #include <gmock/gmock-spec-builders.h>
9 #include "mock_allocator.hpp"
11 #include <ie_blob_proxy.hpp>
13 using namespace ::testing;
15 using namespace InferenceEngine;
16 using namespace InferenceEngine::details;
18 #define MAKE_SHORT(l, h) h * 0x100 + l
20 class BlobProxyTests: public ::testing::Test {
22 virtual void TearDown() {
25 virtual void SetUp() {
28 shared_ptr<MockAllocator> createMockAllocator() {
29 return shared_ptr<MockAllocator>(new MockAllocator());
37 TEST_F(BlobProxyTests, convertByteBlobToFloat) {
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)}));
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++) {
50 TEST_F(BlobProxyTests, shouldThrowOnAllocate) {
51 SizeVector v = {1, 2, 3};
52 auto allocator = createMockAllocator();
54 TBlobProxy<float> proxy(Precision::FP32, C, TBlob<float>(Precision::FP32, CHW, v, dynamic_pointer_cast<IAllocator>(allocator)), 2, {2});
56 EXPECT_THROW(((Blob&)proxy).allocate(), InferenceEngineException);
59 TEST_F(BlobProxyTests, shouldThrowOnDeAllocate)
61 SizeVector v = {1, 2, 3};
62 auto allocator = createMockAllocator();
64 TBlobProxy<float> proxy(Precision::FP32, C, TBlob<float>(Precision::FP32, CHW, v, dynamic_pointer_cast<IAllocator>(allocator)), 2, {2});
66 EXPECT_THROW(((Blob&)proxy).deallocate(), InferenceEngineException);
70 TEST_F(BlobProxyTests, canAccessProxyBlobUsingBaseMethod)
72 SizeVector v = {1, 2, 3};
73 auto allocator = createMockAllocator();
75 float data[] = {5,6,7,8,9,10};
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);
82 TBlob<float> blob(Precision::FP32, CHW, v, dynamic_pointer_cast<IAllocator>(allocator));
85 TBlobProxy<float> proxy(Precision::FP32, C, move(blob), 2, {2});
87 auto proxyBuffer = proxy.buffer();
88 float *ptr = (float*)(void*)proxyBuffer;
89 ASSERT_EQ(ptr[2] , 9);
92 TEST_F(BlobProxyTests, canAccessProxyBlobUsingHelpers)
94 SizeVector v = {1, 2, 3};
95 auto allocator = createMockAllocator();
97 float data[] = {5,6,7, 8, 9, 10};
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);
105 TBlob<float> blob(Precision::FP32, CHW, v, dynamic_pointer_cast<IAllocator>(allocator));
108 TBlobProxy<float> proxy(Precision::FP32, C, std::move(blob), 2, {2});
110 auto proxyData = proxy.data();
111 float *ptr = (float * )&proxyData[0];
112 ASSERT_EQ(ptr[2] , 9);
114 auto readOnly = proxy.readOnly();
115 ptr = (float * )&readOnly[0];
116 ASSERT_EQ(ptr[2] , 9);
119 TEST_F(BlobProxyTests, canCreateProxyBlobFromDifferentBaseBlobType)
121 SizeVector v = {1, 2, 3};
122 auto allocator = createMockAllocator();
124 uint8_t data[] = {5, 6, 7, 8, 9, 10};
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);
131 TBlob<uint8_t > blob(Precision::U8, CHW, v, dynamic_pointer_cast<IAllocator>(allocator));
134 Blob::Ptr spBlob (&blob, [](Blob*){
138 TBlobProxy<short> proxy(Precision::I16, C, spBlob, 0, {3});
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]));
147 TEST_F(BlobProxyTests, canNotCreateBlobWithOffsetOfSizeOutOfOriginal) {
148 SizeVector v = {1, 1, 3};
149 auto allocator = createMockAllocator();
151 EXPECT_CALL(*allocator.get(), alloc(1 * 1 * 3 * sizeof(float))).WillRepeatedly(Return((void*)1));
152 EXPECT_CALL(*allocator.get(), free(_)).Times(1);
154 TBlob<float> blob(Precision::FP32, CHW, v, dynamic_pointer_cast<IAllocator>(allocator));
157 Blob::Ptr spBlob (&blob, [](Blob*){
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);
167 TEST_F(BlobProxyTests, canAccessBothArraysAfterProxying)
169 SizeVector v = {1, 2, 4};
170 auto allocator = createMockAllocator();
172 uint8_t data[] = {5, 6, 7, 8, 9, 10, 11, 12};
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);
179 TBlob<uint8_t> blob(Precision::U8, CHW, v, dynamic_pointer_cast<IAllocator>(allocator));
182 Blob::Ptr spBlob (&blob, [](Blob*){
186 TBlobProxy<short> proxy(Precision::I16, C, spBlob, 2, {3});
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]));
193 auto origBuffer = blob.readOnly();
194 const uint8_t* origPtr = origBuffer;
196 ASSERT_EQ(origPtr[0] , 5);
197 ASSERT_EQ(origPtr[1] , 6);
201 TEST_F(BlobProxyTests, convertTwoByteBlobToFloat) {
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)}));
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++) {
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());
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 });
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";
229 catch (InferenceEngine::details::InferenceEngineException ex) {};
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);
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());
248 TEST_F(BlobProxyTests, canIterateOverData) {
249 TBlob<uint8_t>::Ptr b(new TBlob<uint8_t >(Precision::FP32, C));
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);
256 ASSERT_EQ(2, u8buffer.size());
257 ASSERT_EQ(2, u8buffer[0]);
258 ASSERT_EQ(3, u8buffer[1]);
261 TEST_F(BlobProxyTests, canIterateOverReadOnly) {
262 TBlob<uint8_t>::Ptr b(new TBlob<uint8_t >(Precision::FP32, C));
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);
269 ASSERT_EQ(2, u8buffer.size());
270 ASSERT_EQ(2, u8buffer[0]);
271 ASSERT_EQ(3, u8buffer[1]);