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