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