blob: d9b2e3ffa1137cb3087dbbb0ea4c5a72f22ff708 [file] [log] [blame]
Ian Rogersd582fa42014-11-05 23:46:43 -08001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
xueliang.zhong7f88c1a2018-11-06 11:42:41 +000017#include <array>
18
Ian Rogersd582fa42014-11-05 23:46:43 -080019#include "instruction_set_features.h"
20
21#include <gtest/gtest.h>
22
Bilyan Borisovbb661c02016-04-04 16:27:32 +010023#ifdef ART_TARGET_ANDROID
Andreas Gampe57943812017-12-06 21:39:13 -080024#include <android-base/properties.h>
Ian Rogersd582fa42014-11-05 23:46:43 -080025#endif
26
Andreas Gampe57943812017-12-06 21:39:13 -080027#include <android-base/logging.h>
28#include <android-base/stringprintf.h>
Ian Rogersd582fa42014-11-05 23:46:43 -080029
30namespace art {
31
Andreas Gampebd39d142018-07-19 11:14:42 -070032#ifdef ART_TARGET_ANDROID
33
Andreas Gampe46ee31b2016-12-14 10:11:49 -080034using android::base::StringPrintf;
35
Ian Rogersd9df6702014-11-17 16:43:15 -080036#if defined(__aarch64__)
37TEST(InstructionSetFeaturesTest, DISABLED_FeaturesFromSystemPropertyVariant) {
38 LOG(WARNING) << "Test disabled due to no CPP define for A53 erratum 835769";
39#else
Ian Rogersd582fa42014-11-05 23:46:43 -080040TEST(InstructionSetFeaturesTest, FeaturesFromSystemPropertyVariant) {
Ian Rogersd9df6702014-11-17 16:43:15 -080041#endif
Ian Rogersd582fa42014-11-05 23:46:43 -080042 // Take the default set of instruction features from the build.
43 std::unique_ptr<const InstructionSetFeatures> instruction_set_features(
44 InstructionSetFeatures::FromCppDefines());
45
Ian Rogersd9df6702014-11-17 16:43:15 -080046 // Read the variant property.
Ian Rogersd582fa42014-11-05 23:46:43 -080047 std::string key = StringPrintf("dalvik.vm.isa.%s.variant", GetInstructionSetString(kRuntimeISA));
Dimitry Ivanov9642b1b2016-09-28 02:44:00 -070048 std::string dex2oat_isa_variant = android::base::GetProperty(key, "");
49 if (!dex2oat_isa_variant.empty()) {
Ian Rogersd582fa42014-11-05 23:46:43 -080050 // Use features from property to build InstructionSetFeatures and check against build's
51 // features.
52 std::string error_msg;
53 std::unique_ptr<const InstructionSetFeatures> property_features(
54 InstructionSetFeatures::FromVariant(kRuntimeISA, dex2oat_isa_variant, &error_msg));
55 ASSERT_TRUE(property_features.get() != nullptr) << error_msg;
56
Serban Constantinescud747c132016-10-26 09:30:21 +010057 EXPECT_TRUE(property_features->HasAtLeast(instruction_set_features.get()))
Ian Rogersd582fa42014-11-05 23:46:43 -080058 << "System property features: " << *property_features.get()
59 << "\nFeatures from build: " << *instruction_set_features.get();
60 }
61}
62
Ian Rogersd9df6702014-11-17 16:43:15 -080063#if defined(__aarch64__)
64TEST(InstructionSetFeaturesTest, DISABLED_FeaturesFromSystemPropertyString) {
65 LOG(WARNING) << "Test disabled due to no CPP define for A53 erratum 835769";
66#else
Ian Rogersd582fa42014-11-05 23:46:43 -080067TEST(InstructionSetFeaturesTest, FeaturesFromSystemPropertyString) {
Ian Rogersd9df6702014-11-17 16:43:15 -080068#endif
Ian Rogersd582fa42014-11-05 23:46:43 -080069 // Take the default set of instruction features from the build.
70 std::unique_ptr<const InstructionSetFeatures> instruction_set_features(
71 InstructionSetFeatures::FromCppDefines());
72
Ian Rogersd9df6702014-11-17 16:43:15 -080073 // Read the variant property.
74 std::string variant_key = StringPrintf("dalvik.vm.isa.%s.variant",
75 GetInstructionSetString(kRuntimeISA));
Dimitry Ivanov9642b1b2016-09-28 02:44:00 -070076 std::string dex2oat_isa_variant = android::base::GetProperty(variant_key, "");
77 if (!dex2oat_isa_variant.empty()) {
Ian Rogersd9df6702014-11-17 16:43:15 -080078 // Read the features property.
79 std::string features_key = StringPrintf("dalvik.vm.isa.%s.features",
80 GetInstructionSetString(kRuntimeISA));
Dimitry Ivanov9642b1b2016-09-28 02:44:00 -070081 std::string dex2oat_isa_features = android::base::GetProperty(features_key, "");
82 if (!dex2oat_isa_features.empty()) {
Ian Rogersd9df6702014-11-17 16:43:15 -080083 // Use features from property to build InstructionSetFeatures and check against build's
84 // features.
85 std::string error_msg;
86 std::unique_ptr<const InstructionSetFeatures> base_features(
87 InstructionSetFeatures::FromVariant(kRuntimeISA, dex2oat_isa_variant, &error_msg));
88 ASSERT_TRUE(base_features.get() != nullptr) << error_msg;
Ian Rogersd582fa42014-11-05 23:46:43 -080089
Ian Rogersd9df6702014-11-17 16:43:15 -080090 std::unique_ptr<const InstructionSetFeatures> property_features(
91 base_features->AddFeaturesFromString(dex2oat_isa_features, &error_msg));
92 ASSERT_TRUE(property_features.get() != nullptr) << error_msg;
Ian Rogersd582fa42014-11-05 23:46:43 -080093
Serban Constantinescud747c132016-10-26 09:30:21 +010094 EXPECT_TRUE(property_features->HasAtLeast(instruction_set_features.get()))
Ian Rogersd582fa42014-11-05 23:46:43 -080095 << "System property features: " << *property_features.get()
96 << "\nFeatures from build: " << *instruction_set_features.get();
Ian Rogersd9df6702014-11-17 16:43:15 -080097 }
Ian Rogersd582fa42014-11-05 23:46:43 -080098 }
99}
100
101#if defined(__arm__)
102TEST(InstructionSetFeaturesTest, DISABLED_FeaturesFromCpuInfo) {
103 LOG(WARNING) << "Test disabled due to buggy ARM kernels";
104#else
105TEST(InstructionSetFeaturesTest, FeaturesFromCpuInfo) {
106#endif
107 // Take the default set of instruction features from the build.
108 std::unique_ptr<const InstructionSetFeatures> instruction_set_features(
109 InstructionSetFeatures::FromCppDefines());
110
111 // Check we get the same instruction set features using /proc/cpuinfo.
112 std::unique_ptr<const InstructionSetFeatures> cpuinfo_features(
113 InstructionSetFeatures::FromCpuInfo());
Serban Constantinescud747c132016-10-26 09:30:21 +0100114 EXPECT_TRUE(cpuinfo_features->HasAtLeast(instruction_set_features.get()))
Ian Rogersd582fa42014-11-05 23:46:43 -0800115 << "CPU Info features: " << *cpuinfo_features.get()
116 << "\nFeatures from build: " << *instruction_set_features.get();
117}
118#endif
119
Bilyan Borisovbb661c02016-04-04 16:27:32 +0100120#ifndef ART_TARGET_ANDROID
Ian Rogersd582fa42014-11-05 23:46:43 -0800121TEST(InstructionSetFeaturesTest, HostFeaturesFromCppDefines) {
122 std::string error_msg;
123 std::unique_ptr<const InstructionSetFeatures> default_features(
124 InstructionSetFeatures::FromVariant(kRuntimeISA, "default", &error_msg));
125 ASSERT_TRUE(error_msg.empty());
126
127 std::unique_ptr<const InstructionSetFeatures> cpp_features(
128 InstructionSetFeatures::FromCppDefines());
Serban Constantinescud747c132016-10-26 09:30:21 +0100129 EXPECT_TRUE(cpp_features->HasAtLeast(default_features.get()))
Ian Rogersd582fa42014-11-05 23:46:43 -0800130 << "Default variant features: " << *default_features.get()
131 << "\nFeatures from build: " << *cpp_features.get();
132}
133#endif
134
135#if defined(__arm__)
136TEST(InstructionSetFeaturesTest, DISABLED_FeaturesFromHwcap) {
137 LOG(WARNING) << "Test disabled due to buggy ARM kernels";
138#else
139TEST(InstructionSetFeaturesTest, FeaturesFromHwcap) {
140#endif
141 // Take the default set of instruction features from the build.
142 std::unique_ptr<const InstructionSetFeatures> instruction_set_features(
143 InstructionSetFeatures::FromCppDefines());
144
145 // Check we get the same instruction set features using AT_HWCAP.
146 std::unique_ptr<const InstructionSetFeatures> hwcap_features(
147 InstructionSetFeatures::FromHwcap());
Serban Constantinescud747c132016-10-26 09:30:21 +0100148 EXPECT_TRUE(hwcap_features->HasAtLeast(instruction_set_features.get()))
Ian Rogersd582fa42014-11-05 23:46:43 -0800149 << "Hwcap features: " << *hwcap_features.get()
150 << "\nFeatures from build: " << *instruction_set_features.get();
151}
152
Ian Rogersd582fa42014-11-05 23:46:43 -0800153TEST(InstructionSetFeaturesTest, FeaturesFromAssembly) {
Ian Rogersd582fa42014-11-05 23:46:43 -0800154 // Take the default set of instruction features from the build.
155 std::unique_ptr<const InstructionSetFeatures> instruction_set_features(
156 InstructionSetFeatures::FromCppDefines());
157
158 // Check we get the same instruction set features using assembly tests.
159 std::unique_ptr<const InstructionSetFeatures> assembly_features(
160 InstructionSetFeatures::FromAssembly());
Serban Constantinescud747c132016-10-26 09:30:21 +0100161 EXPECT_TRUE(assembly_features->HasAtLeast(instruction_set_features.get()))
Ian Rogersd582fa42014-11-05 23:46:43 -0800162 << "Assembly features: " << *assembly_features.get()
163 << "\nFeatures from build: " << *instruction_set_features.get();
164}
165
xueliang.zhong7f88c1a2018-11-06 11:42:41 +0000166TEST(InstructionSetFeaturesTest, FeaturesFromRuntimeDetection) {
167 if (!InstructionSetFeatures::IsRuntimeDetectionSupported()) {
168 EXPECT_EQ(InstructionSetFeatures::FromRuntimeDetection(), nullptr);
169 }
170}
171
172// The instruction set feature string must not contain 'default' together with
173// other feature names.
174//
175// Test that InstructionSetFeatures::AddFeaturesFromString returns nullptr and
176// an error is reported when the value 'default' is specified together
177// with other feature names in an instruction set feature string.
178TEST(InstructionSetFeaturesTest, AddFeaturesFromStringWithDefaultAndOtherNames) {
179 std::unique_ptr<const InstructionSetFeatures> cpp_defined_features(
180 InstructionSetFeatures::FromCppDefines());
181 std::vector<std::string> invalid_feature_strings = {
182 "a,default",
183 "default,a",
184 "a,default,b",
185 "a,b,default",
186 "default,a,b,c",
187 "a,b,default,c,d",
188 "a, default ",
189 " default , a",
190 "a, default , b",
191 "default,runtime"
192 };
193
194 for (const std::string& invalid_feature_string : invalid_feature_strings) {
195 std::string error_msg;
196 EXPECT_EQ(cpp_defined_features->AddFeaturesFromString(invalid_feature_string, &error_msg),
197 nullptr) << " Invalid feature string: '" << invalid_feature_string << "'";
198 EXPECT_EQ(error_msg,
199 "Specific instruction set feature(s) cannot be used when 'default' is used.");
200 }
201}
202
203// The instruction set feature string must not contain 'runtime' together with
204// other feature names.
205//
206// Test that InstructionSetFeatures::AddFeaturesFromString returns nullptr and
207// an error is reported when the value 'runtime' is specified together
208// with other feature names in an instruction set feature string.
209TEST(InstructionSetFeaturesTest, AddFeaturesFromStringWithRuntimeAndOtherNames) {
210 std::unique_ptr<const InstructionSetFeatures> cpp_defined_features(
211 InstructionSetFeatures::FromCppDefines());
212 std::vector<std::string> invalid_feature_strings = {
213 "a,runtime",
214 "runtime,a",
215 "a,runtime,b",
216 "a,b,runtime",
217 "runtime,a,b,c",
218 "a,b,runtime,c,d",
219 "a, runtime ",
220 " runtime , a",
221 "a, runtime , b",
222 "runtime,default"
223 };
224
225 for (const std::string& invalid_feature_string : invalid_feature_strings) {
226 std::string error_msg;
227 EXPECT_EQ(cpp_defined_features->AddFeaturesFromString(invalid_feature_string, &error_msg),
228 nullptr) << " Invalid feature string: '" << invalid_feature_string << "'";
229 EXPECT_EQ(error_msg,
230 "Specific instruction set feature(s) cannot be used when 'runtime' is used.");
231 }
232}
233
234// Spaces and multiple commas are ignores in a instruction set feature string.
235//
236// Test that a use of spaces and multiple commas with 'default' and 'runtime'
237// does not cause errors.
238TEST(InstructionSetFeaturesTest, AddFeaturesFromValidStringContainingDefaultOrRuntime) {
239 std::unique_ptr<const InstructionSetFeatures> cpp_defined_features(
240 InstructionSetFeatures::FromCppDefines());
241 std::vector<std::string> valid_feature_strings = {
242 "default",
243 ",,,default",
244 "default,,,,",
245 ",,,default,,,,",
246 "default, , , ",
247 " , , ,default",
248 " , , ,default, , , ",
249 " default , , , ",
250 ",,,runtime",
251 "runtime,,,,",
252 ",,,runtime,,,,",
253 "runtime, , , ",
254 " , , ,runtime",
255 " , , ,runtime, , , ",
256 " runtime , , , "
257 };
258 for (const std::string& valid_feature_string : valid_feature_strings) {
259 std::string error_msg;
260 EXPECT_NE(cpp_defined_features->AddFeaturesFromString(valid_feature_string, &error_msg),
261 nullptr) << " Valid feature string: '" << valid_feature_string << "'";
262 EXPECT_TRUE(error_msg.empty()) << error_msg;
263 }
264}
265
266// Spaces and multiple commas are ignores in a instruction set feature string.
267//
268// Test that a use of spaces and multiple commas without any feature names
269// causes errors.
270TEST(InstructionSetFeaturesTest, AddFeaturesFromInvalidStringWithoutFeatureNames) {
271 std::unique_ptr<const InstructionSetFeatures> cpp_defined_features(
272 InstructionSetFeatures::FromCppDefines());
273 std::vector<std::string> invalid_feature_strings = {
274 " ",
275 " ",
276 ",",
277 ",,",
278 " , , ,,,,,,",
279 "\t",
280 " \t ",
281 ",",
282 ",,",
283 " , , ,,,,,,"
284 };
285 for (const std::string& invalid_feature_string : invalid_feature_strings) {
286 std::string error_msg;
287 EXPECT_EQ(cpp_defined_features->AddFeaturesFromString(invalid_feature_string, &error_msg),
288 nullptr) << " Invalid feature string: '" << invalid_feature_string << "'";
289 EXPECT_EQ(error_msg, "No instruction set features specified");
290 }
291}
292
293TEST(InstructionSetFeaturesTest, AddFeaturesFromStringRuntime) {
294 std::unique_ptr<const InstructionSetFeatures> cpp_defined_features(
295 InstructionSetFeatures::FromCppDefines());
296 std::string error_msg;
297
298 const std::unique_ptr<const InstructionSetFeatures> features =
299 cpp_defined_features->AddFeaturesFromString("runtime", &error_msg);
300 EXPECT_NE(features, nullptr);
301 EXPECT_TRUE(error_msg.empty()) << error_msg;
302 if (!InstructionSetFeatures::IsRuntimeDetectionSupported()) {
303 EXPECT_TRUE(features->Equals(cpp_defined_features.get()));
304 }
305}
306
Ian Rogersd582fa42014-11-05 23:46:43 -0800307} // namespace art