1 /* Copyright 2015 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 
16 #include "tensorflow/core/framework/types.h"
17 
18 #include "tensorflow/core/framework/type_traits.h"
19 #include "tensorflow/core/lib/strings/str_util.h"
20 #include "tensorflow/core/platform/protobuf.h"
21 #include "tensorflow/core/platform/test.h"
22 
23 namespace tensorflow {
24 namespace {
25 
TEST(TypesTest,DeviceTypeName)26 TEST(TypesTest, DeviceTypeName) {
27   EXPECT_EQ("CPU", DeviceTypeString(DeviceType(DEVICE_CPU)));
28   EXPECT_EQ("GPU", DeviceTypeString(DeviceType(DEVICE_GPU)));
29   EXPECT_EQ("SYCL", DeviceTypeString(DeviceType(DEVICE_SYCL)));
30 }
31 
TEST(TypesTest,kDataTypeRefOffset)32 TEST(TypesTest, kDataTypeRefOffset) {
33   // Basic sanity check
34   EXPECT_EQ(DT_FLOAT + kDataTypeRefOffset, DT_FLOAT_REF);
35 
36   // Use the meta-data provided by proto2 to iterate through the basic
37   // types and validate that adding kDataTypeRefOffset gives the
38   // corresponding reference type.
39   const auto* enum_descriptor = DataType_descriptor();
40   int e = DataType_MIN;
41   if (e == DT_INVALID) ++e;
42   int e_ref = e + kDataTypeRefOffset;
43   EXPECT_FALSE(DataType_IsValid(e_ref - 1))
44       << "Reference enum "
45       << enum_descriptor->FindValueByNumber(e_ref - 1)->name()
46       << " without corresponding base enum with value " << e - 1;
47   for (;
48        DataType_IsValid(e) && DataType_IsValid(e_ref) && e_ref <= DataType_MAX;
49        ++e, ++e_ref) {
50     string enum_name = enum_descriptor->FindValueByNumber(e)->name();
51     string enum_ref_name = enum_descriptor->FindValueByNumber(e_ref)->name();
52     EXPECT_EQ(enum_name + "_REF", enum_ref_name)
53         << enum_name << "_REF should have value " << e_ref << " not "
54         << enum_ref_name;
55     // Validate DataTypeString() as well.
56     DataType dt_e = static_cast<DataType>(e);
57     DataType dt_e_ref = static_cast<DataType>(e_ref);
58     EXPECT_EQ(DataTypeString(dt_e) + "_ref", DataTypeString(dt_e_ref));
59 
60     // Test DataTypeFromString reverse conversion
61     DataType dt_e2, dt_e2_ref;
62     EXPECT_TRUE(DataTypeFromString(DataTypeString(dt_e), &dt_e2));
63     EXPECT_EQ(dt_e, dt_e2);
64     EXPECT_TRUE(DataTypeFromString(DataTypeString(dt_e_ref), &dt_e2_ref));
65     EXPECT_EQ(dt_e_ref, dt_e2_ref);
66   }
67   ASSERT_FALSE(DataType_IsValid(e))
68       << "Should define " << enum_descriptor->FindValueByNumber(e)->name()
69       << "_REF to be " << e_ref;
70   ASSERT_FALSE(DataType_IsValid(e_ref))
71       << "Extra reference enum "
72       << enum_descriptor->FindValueByNumber(e_ref)->name()
73       << " without corresponding base enum with value " << e;
74   ASSERT_LT(DataType_MAX, e_ref)
75       << "Gap in reference types, missing value for " << e_ref;
76 
77   // Make sure there are no enums defined after the last regular type before
78   // the first reference type.
79   for (; e < DataType_MIN + kDataTypeRefOffset; ++e) {
80     EXPECT_FALSE(DataType_IsValid(e))
81         << "Discontinuous enum value "
82         << enum_descriptor->FindValueByNumber(e)->name() << " = " << e;
83   }
84 }
85 
TEST(TypesTest,DataTypeFromString)86 TEST(TypesTest, DataTypeFromString) {
87   DataType dt;
88   ASSERT_TRUE(DataTypeFromString("int32", &dt));
89   EXPECT_EQ(DT_INT32, dt);
90   ASSERT_TRUE(DataTypeFromString("int32_ref", &dt));
91   EXPECT_EQ(DT_INT32_REF, dt);
92   EXPECT_FALSE(DataTypeFromString("int32_ref_ref", &dt));
93   EXPECT_FALSE(DataTypeFromString("foo", &dt));
94   EXPECT_FALSE(DataTypeFromString("foo_ref", &dt));
95   ASSERT_TRUE(DataTypeFromString("int64", &dt));
96   EXPECT_EQ(DT_INT64, dt);
97   ASSERT_TRUE(DataTypeFromString("int64_ref", &dt));
98   EXPECT_EQ(DT_INT64_REF, dt);
99   ASSERT_TRUE(DataTypeFromString("quint8_ref", &dt));
100   EXPECT_EQ(DT_QUINT8_REF, dt);
101   ASSERT_TRUE(DataTypeFromString("bfloat16", &dt));
102   EXPECT_EQ(DT_BFLOAT16, dt);
103 }
104 
105 template <typename T>
GetQuantized()106 static bool GetQuantized() {
107   return is_quantized<T>::value;
108 }
109 
TEST(TypesTest,QuantizedTypes)110 TEST(TypesTest, QuantizedTypes) {
111   // NOTE: GUnit cannot parse is::quantized<TYPE>::value() within the
112   // EXPECT_TRUE() clause, so we delegate through a template function.
113   EXPECT_TRUE(GetQuantized<qint8>());
114   EXPECT_TRUE(GetQuantized<quint8>());
115   EXPECT_TRUE(GetQuantized<qint32>());
116 
117   EXPECT_FALSE(GetQuantized<int8>());
118   EXPECT_FALSE(GetQuantized<uint8>());
119   EXPECT_FALSE(GetQuantized<int16>());
120   EXPECT_FALSE(GetQuantized<int32>());
121 
122   EXPECT_TRUE(DataTypeIsQuantized(DT_QINT8));
123   EXPECT_TRUE(DataTypeIsQuantized(DT_QUINT8));
124   EXPECT_TRUE(DataTypeIsQuantized(DT_QINT32));
125 
126   EXPECT_FALSE(DataTypeIsQuantized(DT_INT8));
127   EXPECT_FALSE(DataTypeIsQuantized(DT_UINT8));
128   EXPECT_FALSE(DataTypeIsQuantized(DT_UINT16));
129   EXPECT_FALSE(DataTypeIsQuantized(DT_INT16));
130   EXPECT_FALSE(DataTypeIsQuantized(DT_INT32));
131   EXPECT_FALSE(DataTypeIsQuantized(DT_BFLOAT16));
132 }
133 
TEST(TypesTest,ComplexTypes)134 TEST(TypesTest, ComplexTypes) {
135   EXPECT_TRUE(DataTypeIsComplex(DT_COMPLEX64));
136   EXPECT_TRUE(DataTypeIsComplex(DT_COMPLEX128));
137   EXPECT_FALSE(DataTypeIsComplex(DT_FLOAT));
138   EXPECT_FALSE(DataTypeIsComplex(DT_DOUBLE));
139 }
140 
TEST(TypesTest,IntegerTypes)141 TEST(TypesTest, IntegerTypes) {
142   for (auto dt : AllTypes()) {
143     const string name = DataTypeString(dt);
144     EXPECT_EQ(DataTypeIsInteger(dt), str_util::StartsWith(name, "int") ||
145                                          str_util::StartsWith(name, "uint"))
146         << "DataTypeInteger failed for " << name;
147   }
148 }
149 
150 }  // namespace
151 }  // namespace tensorflow
152