• 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/common.h"
21 #include "tensorflow/lite/util.h"
22 
23 namespace tflite {
24 namespace resource {
25 // Helper util that initialize 'tensor'.
InitTensor(const std::vector<int> & shape,TfLiteAllocationType alloc_type,float default_value,TfLiteTensor * tensor)26 void InitTensor(const std::vector<int>& shape, TfLiteAllocationType alloc_type,
27                 float default_value, TfLiteTensor* tensor) {
28   memset(tensor, 0, sizeof(TfLiteTensor));
29   int num_elements = 1;
30   for (auto dim : shape) num_elements *= dim;
31   if (shape.empty()) num_elements = 0;
32   float* buf = static_cast<float*>(malloc(sizeof(float) * num_elements));
33   for (int i = 0; i < num_elements; ++i) buf[i] = default_value;
34   const int bytes = num_elements * sizeof(buf[0]);
35   auto* dims = ConvertArrayToTfLiteIntArray(shape.size(), shape.data());
36   TfLiteTensorReset(TfLiteType::kTfLiteFloat32, nullptr, dims, {},
37                     reinterpret_cast<char*>(buf), bytes, alloc_type, nullptr,
38                     false, tensor);
39 }
40 
TEST(ResourceTest,NonDynamicTensorAssign)41 TEST(ResourceTest, NonDynamicTensorAssign) {
42   ResourceVariable var;
43   EXPECT_FALSE(var.IsInitialized());
44 
45   TfLiteTensor tensor;
46   std::vector<int> shape = {1};
47   InitTensor(shape, kTfLiteArenaRw, 1.0f, &tensor);
48 
49   EXPECT_EQ(kTfLiteOk, var.AssignFrom(&tensor));
50   EXPECT_TRUE(var.IsInitialized());
51   auto* value = var.GetTensor();
52 
53   // Variables are always dynamic type.
54   EXPECT_EQ(kTfLiteDynamic, value->allocation_type);
55   EXPECT_EQ(kTfLiteFloat32, value->type);
56   EXPECT_EQ(sizeof(float), value->bytes);
57   EXPECT_EQ(1, value->dims->size);
58   EXPECT_EQ(1, value->dims->data[0]);
59   EXPECT_EQ(1.0f, value->data.f[0]);
60 
61   // Cleanup
62   // For non dynamic tensors we need to delete the buffers manually.
63   free(tensor.data.raw);
64   TfLiteTensorFree(&tensor);
65 }
66 
TEST(ResourceTest,DynamicTensorAssign)67 TEST(ResourceTest, DynamicTensorAssign) {
68   ResourceVariable var;
69   EXPECT_FALSE(var.IsInitialized());
70 
71   TfLiteTensor tensor;
72   std::vector<int> shape = {1};
73   InitTensor(shape, kTfLiteDynamic, 1.0f, &tensor);
74 
75   EXPECT_EQ(kTfLiteOk, var.AssignFrom(&tensor));
76   EXPECT_TRUE(var.IsInitialized());
77   auto* value = var.GetTensor();
78 
79   // Variables are always dynamic type.
80   EXPECT_EQ(kTfLiteDynamic, value->allocation_type);
81   EXPECT_EQ(kTfLiteFloat32, value->type);
82   EXPECT_EQ(sizeof(float), value->bytes);
83   EXPECT_EQ(1, value->dims->size);
84   EXPECT_EQ(1, value->dims->data[0]);
85   EXPECT_EQ(1.0f, value->data.f[0]);
86 
87   // Cleanup
88   TfLiteTensorFree(&tensor);
89 }
90 
TEST(ResourceTest,AssignSameSizeTensor)91 TEST(ResourceTest, AssignSameSizeTensor) {
92   ResourceVariable var;
93   EXPECT_FALSE(var.IsInitialized());
94 
95   // We create 2 tensors and make 2 calls for Assign.
96   // The second Assign call should trigger the case of assign with same size.
97   TfLiteTensor tensor_a, tensor_b;
98   std::vector<int> shape_a = {1};
99   std::vector<int> shape_b = {1};
100   InitTensor(shape_a, kTfLiteDynamic, 1.0, &tensor_a);
101   InitTensor(shape_b, kTfLiteDynamic, 4.0, &tensor_b);
102 
103   EXPECT_EQ(kTfLiteOk, var.AssignFrom(&tensor_a));
104   EXPECT_TRUE(var.IsInitialized());
105   auto* value = var.GetTensor();
106   // Variables are always dynamic type.
107   EXPECT_EQ(kTfLiteDynamic, value->allocation_type);
108   EXPECT_EQ(kTfLiteFloat32, value->type);
109   EXPECT_EQ(sizeof(float), value->bytes);
110   EXPECT_EQ(1, value->dims->size);
111   EXPECT_EQ(1, value->dims->data[0]);
112   EXPECT_EQ(1.0f, value->data.f[0]);
113 
114   // Second AssignFrom but now tensor_b has same size as the variable.
115   EXPECT_EQ(kTfLiteOk, var.AssignFrom(&tensor_b));
116   EXPECT_TRUE(var.IsInitialized());
117   value = var.GetTensor();
118   // Variables are always dynamic type.
119   EXPECT_EQ(kTfLiteDynamic, value->allocation_type);
120   EXPECT_EQ(kTfLiteFloat32, value->type);
121   EXPECT_EQ(sizeof(float), value->bytes);
122   EXPECT_EQ(1, value->dims->size);
123   EXPECT_EQ(1, value->dims->data[0]);
124   EXPECT_EQ(4.0f, value->data.f[0]);
125 
126   // Cleanup
127   TfLiteTensorFree(&tensor_a);
128   TfLiteTensorFree(&tensor_b);
129 }
130 
TEST(ResourceTest,AssignDifferentSizeTensor)131 TEST(ResourceTest, AssignDifferentSizeTensor) {
132   ResourceVariable var;
133   EXPECT_FALSE(var.IsInitialized());
134 
135   // We create 2 tensors and make 2 calls for Assign.
136   // The second Assign call should trigger the case of assign with different
137   // size.
138   TfLiteTensor tensor_a, tensor_b;
139   std::vector<int> shape_a = {1};
140   std::vector<int> shape_b = {2};
141   InitTensor(shape_a, kTfLiteDynamic, 1.0, &tensor_a);
142   InitTensor(shape_b, kTfLiteDynamic, 4.0, &tensor_b);
143 
144   EXPECT_EQ(kTfLiteOk, var.AssignFrom(&tensor_a));
145   EXPECT_TRUE(var.IsInitialized());
146   auto* value = var.GetTensor();
147   // Variables are always dynamic type.
148   EXPECT_EQ(kTfLiteDynamic, value->allocation_type);
149   EXPECT_EQ(kTfLiteFloat32, value->type);
150   EXPECT_EQ(sizeof(float), value->bytes);
151   EXPECT_EQ(1, value->dims->size);
152   EXPECT_EQ(1, value->dims->data[0]);
153   EXPECT_EQ(1.0f, value->data.f[0]);
154 
155   // Second AssignFrom but now tensor_b has different size from the variable.
156   EXPECT_EQ(kTfLiteOk, var.AssignFrom(&tensor_b));
157   EXPECT_TRUE(var.IsInitialized());
158   value = var.GetTensor();
159   // Variables are always dynamic type.
160   EXPECT_EQ(kTfLiteDynamic, value->allocation_type);
161   EXPECT_EQ(kTfLiteFloat32, value->type);
162   EXPECT_EQ(sizeof(float) * 2, value->bytes);
163   EXPECT_EQ(1, value->dims->size);
164   EXPECT_EQ(2, value->dims->data[0]);
165   EXPECT_EQ(4.0f, value->data.f[0]);
166 
167   // Cleanup
168   TfLiteTensorFree(&tensor_a);
169   TfLiteTensorFree(&tensor_b);
170 }
171 
172 }  // namespace resource
173 }  // namespace tflite
174