1 /* Copyright 2021 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/acceleration/mini_benchmark/mini_benchmark_test_helper.h"
16
17 #include <fcntl.h>
18
19 #include <string>
20 #ifndef _WIN32
21 #include <dlfcn.h>
22 #include <signal.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #endif // !_WIN32
26
27 #include <fstream>
28
29 #include <gtest/gtest.h>
30 #include "tensorflow/lite/experimental/acceleration/compatibility/android_info.h"
31 #include "tensorflow/lite/tools/logging.h"
32
33 #ifdef __ANDROID__
34 #include "tensorflow/lite/experimental/acceleration/mini_benchmark/embedded_runner_executable.h"
35 #include "tensorflow/lite/experimental/acceleration/mini_benchmark/embedded_validator_runner_entrypoint.h"
36 #endif // __ANDROID__
37
38 namespace tflite {
39 namespace acceleration {
40 namespace {
41 #ifdef __ANDROID__
LoadEntryPointModule(const std::string & module_path)42 void* LoadEntryPointModule(const std::string& module_path) {
43 void* module =
44 dlopen(module_path.c_str(), RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
45 if (module == nullptr) {
46 TFLITE_LOG(FATAL) << dlerror();
47 }
48 return module;
49 }
50 #endif // __ANDROID__
51
JoinPath(const std::string & path1,const std::string & path2)52 std::string JoinPath(const std::string& path1, const std::string& path2) {
53 if (path1.empty()) return path2;
54 if (path2.empty()) return path1;
55 if (path1.back() == '/') {
56 if (path2.front() == '/') return path1 + path2.substr(1);
57 } else {
58 if (path2.front() != '/') return path1 + "/" + path2;
59 }
60 return path1 + path2;
61 }
62 } // namespace
63
MiniBenchmarkTestHelper()64 MiniBenchmarkTestHelper::MiniBenchmarkTestHelper()
65 : should_perform_test_(true) {
66 #ifdef __ANDROID__
67 AndroidInfo android_info;
68 const auto status = RequestAndroidInfo(&android_info);
69 if (!status.ok() || android_info.is_emulator) {
70 should_perform_test_ = false;
71 return;
72 }
73
74 DumpToTempFile("librunner_main.so", g_tflite_acceleration_embedded_runner,
75 g_tflite_acceleration_embedded_runner_len);
76
77 std::string validator_runner_so_path = DumpToTempFile(
78 "libvalidator_runner_entrypoint.so",
79 g_tflite_acceleration_embedded_validator_runner_entrypoint,
80 g_tflite_acceleration_embedded_validator_runner_entrypoint_len);
81 // Load this library here because it contains the validation entry point
82 // "Java_org_tensorflow_lite_acceleration_validation_entrypoint" that is then
83 // found using dlsym (using RTLD_DEFAULT hence not needing the handle) in the
84 // mini-benchmark code.
85 LoadEntryPointModule(validator_runner_so_path);
86 #endif // __ANDROID__
87 }
88
DumpToTempFile(const std::string & filename,const unsigned char * data,size_t length)89 std::string MiniBenchmarkTestHelper::DumpToTempFile(const std::string& filename,
90 const unsigned char* data,
91 size_t length) {
92 std::string path = JoinPath(::testing::TempDir(), filename);
93 (void)unlink(path.c_str());
94 std::string contents(reinterpret_cast<const char*>(data), length);
95 std::ofstream f(path, std::ios::binary);
96 EXPECT_TRUE(f.is_open());
97 f << contents;
98 f.close();
99 EXPECT_EQ(0, chmod(path.c_str(), 0500));
100 return path;
101 }
102
103 } // namespace acceleration
104 } // namespace tflite
105