• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 #include "tensorflow/lite/experimental/resource/resource_variable.h"
16 
17 #include <vector>
18 
19 #include <gtest/gtest.h>
20 #include "tensorflow/lite/c/c_api_types.h"
21 #include "tensorflow/lite/c/common.h"
22 #include "tensorflow/lite/util.h"
23 
24 namespace tflite {
25 namespace resource {
26 // Helper util that initialize 'tensor'.
InitTensor(const std::vector<int> & shape,TfLiteAllocationType alloc_type,float default_value,TfLiteTensor * tensor)27 void InitTensor(const std::vector<int>& shape, TfLiteAllocationType alloc_type,
28                 float default_value, TfLiteTensor* tensor) {
29   memset(tensor, 0, sizeof(TfLiteTensor));
30   int num_elements = 1;
31   for (auto dim : shape) num_elements *= dim;
32   if (shape.empty()) num_elements = 0;
33   float* buf = static_cast<float*>(malloc(sizeof(float) * num_elements));
34   for (int i = 0; i < num_elements; ++i) buf[i] = default_value;
35   const int bytes = num_elements * sizeof(buf[0]);
36   auto* dims = ConvertArrayToTfLiteIntArray(shape.size(), shape.data());
37   TfLiteTensorReset(TfLiteType::kTfLiteFloat32, nullptr, dims, {},
38                     reinterpret_cast<char*>(buf), bytes, alloc_type, nullptr,
39                     false, tensor);
40 }
41 
TEST(ResourceTest,NonDynamicTensorAssign)42 TEST(ResourceTest, NonDynamicTensorAssign) {
43   ResourceVariable var;
44   EXPECT_FALSE(var.IsInitialized());
45 
46   TfLiteTensor tensor;
47   std::vector<int> shape = {1};
48   InitTensor(shape, kTfLiteArenaRw, 1.0f, &tensor);
49 
50   EXPECT_EQ(kTfLiteOk, var.AssignFrom(&tensor));
51   EXPECT_TRUE(var.IsInitialized());
52   auto* value = var.GetTensor();
53 
54   // Variables are always dynamic type.
55   EXPECT_EQ(kTfLiteDynamic, value->allocation_type);
56   EXPECT_EQ(kTfLiteFloat32, value->type);
57   EXPECT_EQ(sizeof(float), value->bytes);
58   EXPECT_EQ(1, value->dims->size);
59   EXPECT_EQ(1, value->dims->data[0]);
60   EXPECT_EQ(1.0f, value->data.f[0]);
61 
62   // Cleanup
63   // For non dynamic tensors we need to delete the buffers manually.
64   free(tensor.data.raw);
65   TfLiteTensorFree(&tensor);
66 }
67 
TEST(ResourceTest,DynamicTensorAssign)68 TEST(ResourceTest, DynamicTensorAssign) {
69   ResourceVariable var;
70   EXPECT_FALSE(var.IsInitialized());
71 
72   TfLiteTensor tensor;
73   std::vector<int> shape = {1};
74   InitTensor(shape, kTfLiteDynamic, 1.0f, &tensor);
75 
76   EXPECT_EQ(kTfLiteOk, var.AssignFrom(&tensor));
77   EXPECT_TRUE(var.IsInitialized());
78   auto* value = var.GetTensor();
79 
80   // Variables are always dynamic type.
81   EXPECT_EQ(kTfLiteDynamic, value->allocation_type);
82   EXPECT_EQ(kTfLiteFloat32, value->type);
83   EXPECT_EQ(sizeof(float), value->bytes);
84   EXPECT_EQ(1, value->dims->size);
85   EXPECT_EQ(1, value->dims->data[0]);
86   EXPECT_EQ(1.0f, value->data.f[0]);
87 
88   // Cleanup
89   TfLiteTensorFree(&tensor);
90 }
91 
TEST(ResourceTest,AssignSameSizeTensor)92 TEST(ResourceTest, AssignSameSizeTensor) {
93   ResourceVariable var;
94   EXPECT_FALSE(var.IsInitialized());
95 
96   // We create 2 tensors and make 2 calls for Assign.
97   // The second Assign call should trigger the case of assign with same size.
98   TfLiteTensor tensor_a, tensor_b;
99   std::vector<int> shape_a = {1};
100   std::vector<int> shape_b = {1};
101   InitTensor(shape_a, kTfLiteDynamic, 1.0, &tensor_a);
102   InitTensor(shape_b, kTfLiteDynamic, 4.0, &tensor_b);
103 
104   EXPECT_EQ(kTfLiteOk, var.AssignFrom(&tensor_a));
105   EXPECT_TRUE(var.IsInitialized());
106   auto* value = var.GetTensor();
107   // Variables are always dynamic type.
108   EXPECT_EQ(kTfLiteDynamic, value->allocation_type);
109   EXPECT_EQ(kTfLiteFloat32, value->type);
110   EXPECT_EQ(sizeof(float), value->bytes);
111   EXPECT_EQ(1, value->dims->size);
112   EXPECT_EQ(1, value->dims->data[0]);
113   EXPECT_EQ(1.0f, value->data.f[0]);
114 
115   // Second AssignFrom but now tensor_b has same size as the variable.
116   EXPECT_EQ(kTfLiteOk, var.AssignFrom(&tensor_b));
117   EXPECT_TRUE(var.IsInitialized());
118   value = var.GetTensor();
119   // Variables are always dynamic type.
120   EXPECT_EQ(kTfLiteDynamic, value->allocation_type);
121   EXPECT_EQ(kTfLiteFloat32, value->type);
122   EXPECT_EQ(sizeof(float), value->bytes);
123   EXPECT_EQ(1, value->dims->size);
124   EXPECT_EQ(1, value->dims->data[0]);
125   EXPECT_EQ(4.0f, value->data.f[0]);
126 
127   // Cleanup
128   TfLiteTensorFree(&tensor_a);
129   TfLiteTensorFree(&tensor_b);
130 }
131 
TEST(ResourceTest,AssignDifferentSizeTensor)132 TEST(ResourceTest, AssignDifferentSizeTensor) {
133   ResourceVariable var;
134   EXPECT_FALSE(var.IsInitialized());
135 
136   // We create 2 tensors and make 2 calls for Assign.
137   // The second Assign call should trigger the case of assign with different
138   // size.
139   TfLiteTensor tensor_a, tensor_b;
140   std::vector<int> shape_a = {1};
141   std::vector<int> shape_b = {2};
142   InitTensor(shape_a, kTfLiteDynamic, 1.0, &tensor_a);
143   InitTensor(shape_b, kTfLiteDynamic, 4.0, &tensor_b);
144 
145   EXPECT_EQ(kTfLiteOk, var.AssignFrom(&tensor_a));
146   EXPECT_TRUE(var.IsInitialized());
147   auto* value = var.GetTensor();
148   // Variables are always dynamic type.
149   EXPECT_EQ(kTfLiteDynamic, value->allocation_type);
150   EXPECT_EQ(kTfLiteFloat32, value->type);
151   EXPECT_EQ(sizeof(float), value->bytes);
152   EXPECT_EQ(1, value->dims->size);
153   EXPECT_EQ(1, value->dims->data[0]);
154   EXPECT_EQ(1.0f, value->data.f[0]);
155 
156   // Second AssignFrom but now tensor_b has different size from the variable.
157   EXPECT_EQ(kTfLiteOk, var.AssignFrom(&tensor_b));
158   EXPECT_TRUE(var.IsInitialized());
159   value = var.GetTensor();
160   // Variables are always dynamic type.
161   EXPECT_EQ(kTfLiteDynamic, value->allocation_type);
162   EXPECT_EQ(kTfLiteFloat32, value->type);
163   EXPECT_EQ(sizeof(float) * 2, value->bytes);
164   EXPECT_EQ(1, value->dims->size);
165   EXPECT_EQ(2, value->dims->data[0]);
166   EXPECT_EQ(4.0f, value->data.f[0]);
167 
168   // Cleanup
169   TfLiteTensorFree(&tensor_a);
170   TfLiteTensorFree(&tensor_b);
171 }
172 
TEST(IsBuiltinResource,IsBuiltinResourceTest)173 TEST(IsBuiltinResource, IsBuiltinResourceTest) {
174   TfLiteTensor tensor;
175   tensor.type = kTfLiteResource;
176   tensor.delegate = nullptr;
177   // Resource type and not delegate output.
178   EXPECT_TRUE(IsBuiltinResource(&tensor));
179 
180   // Not valid tensor.
181   EXPECT_FALSE(IsBuiltinResource(nullptr));
182 
183   // Not a resource type.
184   tensor.type = kTfLiteFloat32;
185   EXPECT_FALSE(IsBuiltinResource(&tensor));
186 
187   // Resource but coming from a delegate.
188   tensor.type = kTfLiteResource;
189   TfLiteDelegate delegate;
190   tensor.delegate = &delegate;
191   EXPECT_FALSE(IsBuiltinResource(&tensor));
192 }
193 
TEST(ResourceTest,GetMemoryUsage)194 TEST(ResourceTest, GetMemoryUsage) {
195   ResourceVariable var;
196   EXPECT_FALSE(var.IsInitialized());
197 
198   TfLiteTensor tensor;
199   std::vector<int> shape = {100};
200   InitTensor(shape, kTfLiteArenaRw, 1.0f, &tensor);
201 
202   EXPECT_EQ(kTfLiteOk, var.AssignFrom(&tensor));
203   EXPECT_TRUE(var.IsInitialized());
204   auto* value = var.GetTensor();
205 
206   // Variables are always dynamic type.
207   EXPECT_EQ(kTfLiteDynamic, value->allocation_type);
208   EXPECT_EQ(kTfLiteFloat32, value->type);
209   EXPECT_EQ(100 * sizeof(float), value->bytes);
210   EXPECT_EQ(1, value->dims->size);
211   EXPECT_EQ(100, value->dims->data[0]);
212   EXPECT_EQ(1.0f, value->data.f[0]);
213 
214   // Check memory usage
215   EXPECT_EQ(100 * sizeof(float), var.GetMemoryUsage());
216 
217   // Cleanup
218   // For non dynamic tensors we need to delete the buffers manually.
219   free(tensor.data.raw);
220   TfLiteTensorFree(&tensor);
221 }
222 
223 }  // namespace resource
224 }  // namespace tflite
225