16 #include "tensorflow_serving/servables/tensorflow/bundle_factory_test_util.h"
24 #include "tensorflow/cc/saved_model/constants.h"
25 #include "tensorflow/core/framework/tensor.h"
26 #include "tensorflow/core/framework/tensor_testutil.h"
27 #include "tensorflow/core/lib/core/status.h"
28 #include "tensorflow/core/lib/core/status_test_util.h"
29 #include "tensorflow/core/lib/io/path.h"
30 #include "tensorflow/core/platform/env.h"
31 #include "tensorflow/core/platform/threadpool_options.h"
32 #include "tensorflow_serving/resources/resource_values.h"
33 #include "tensorflow_serving/test_util/test_util.h"
35 namespace tensorflow {
41 const char kTestSavedModelPath[] =
42 "cc/saved_model/testdata/half_plus_two/00000123";
43 const char kTestSessionBundleExportPath[] =
44 "session_bundle/testdata/half_plus_two/00000123";
45 const char kTestTfLiteModelPath[] =
46 "servables/tensorflow/testdata/saved_model_half_plus_two_tflite/00000123";
47 const char kTestMLMDSavedModelPath[] =
48 "servables/tensorflow/testdata/half_plus_two_mlmd/00000123";
52 string GetTestSavedModelPath() {
53 return test_util::TensorflowTestSrcDirPath(kTestSavedModelPath);
56 string GetTestMLMetadataSavedModelPath() {
57 return test_util::TensorflowTestSrcDirPath(kTestMLMDSavedModelPath);
60 string GetTestSessionBundleExportPath() {
61 return test_util::TestSrcDirPath(kTestSessionBundleExportPath);
64 string GetTestTfLiteModelPath() {
65 return test_util::TestSrcDirPath(kTestTfLiteModelPath);
68 std::vector<string> GetTestSessionBundleExportFiles() {
69 const string dir = GetTestSessionBundleExportPath();
70 return {tensorflow::io::JoinPath(dir,
"export.meta"),
71 tensorflow::io::JoinPath(dir,
"export-00000-of-00001")};
74 std::vector<string> GetTestSavedModelBundleExportFiles() {
75 const string dir = GetTestSavedModelPath();
77 tensorflow::io::JoinPath(dir,
"saved_model.pb"),
78 tensorflow::io::JoinPath(dir,
"assets/foo.txt"),
79 tensorflow::io::JoinPath(dir,
"variables/variables.index"),
80 tensorflow::io::JoinPath(dir,
"variables/variables.data-00000-of-00001")};
83 uint64_t GetTotalFileSize(
const std::vector<string>& files) {
84 uint64_t total_file_size = 0;
85 for (
const string& file : files) {
86 if (!(Env::Default()->IsDirectory(file).ok()) &&
87 Env::Default()->FileExists(file).ok()) {
89 TF_CHECK_OK(Env::Default()->GetFileSize(file, &file_size));
90 total_file_size += file_size;
93 return total_file_size;
96 SignatureDef GetTestSessionSignature() {
97 SignatureDef signature;
99 input.set_name(
"x:0");
100 (*signature.mutable_inputs())[
"x"] = input;
102 output.set_name(
"y:0");
103 (*signature.mutable_outputs())[
"y"] = output;
107 void TestSingleRequest(Session* session,
int input_batch_size) {
108 Tensor input(DT_FLOAT, TensorShape({input_batch_size}));
109 test::FillIota<float>(&input, 100.0f);
111 Tensor expected_output(DT_FLOAT, TensorShape({input_batch_size}));
112 test::FillFn<float>(&expected_output,
113 [](
int i) ->
float {
return (100.0f + i) / 2 + 2; });
118 const std::vector<std::pair<string, Tensor>> inputs = {{
"x:0", input}};
119 const std::vector<string> output_names = {
"y:0"};
120 const std::vector<string> empty_targets;
121 std::vector<Tensor> outputs;
123 RunMetadata run_metadata;
124 TF_ASSERT_OK(session->Run(RunOptions{}, inputs, output_names, empty_targets,
125 &outputs, &run_metadata,
126 thread::ThreadPoolOptions{}));
128 ASSERT_EQ(1, outputs.size());
129 const auto& single_output = outputs.at(0);
130 test::ExpectTensorEqual<float>(expected_output, single_output);
133 void TestMultipleRequests(Session* session,
int num_requests,
134 int input_batch_size) {
135 std::vector<std::unique_ptr<Thread>> request_threads;
136 request_threads.reserve(num_requests);
137 for (
int i = 0; i < num_requests; ++i) {
138 request_threads.push_back(
139 std::unique_ptr<Thread>(Env::Default()->StartThread(
140 ThreadOptions(), strings::StrCat(
"thread_", i),
141 [session, input_batch_size] {
142 TestSingleRequest(session, input_batch_size);
147 ResourceAllocation GetExpectedResourceEstimate(
double total_file_size) {
150 const double kResourceEstimateRAMMultiplier = 1.2;
151 const int kResourceEstimateRAMPadBytes = 0;
152 const uint64_t expected_ram_requirement =
153 total_file_size * kResourceEstimateRAMMultiplier +
154 kResourceEstimateRAMPadBytes;
155 ResourceAllocation resource_alloc;
156 ResourceAllocation::Entry* ram_entry =
157 resource_alloc.add_resource_quantities();
158 Resource* ram_resource = ram_entry->mutable_resource();
159 ram_resource->set_device(device_types::kMain);
160 ram_resource->set_kind(resource_kinds::kRamBytes);
161 ram_entry->set_quantity(expected_ram_requirement);
162 return resource_alloc;
165 void CopyDirOrDie(
const string& src_dir,
const string& dst_dir) {
168 if (Env::Default()->IsDirectory(dst_dir).ok()) {
169 TF_ASSERT_OK(Env::Default()->DeleteRecursively(dst_dir, &u_files, &u_dirs));
171 TF_ASSERT_OK(Env::Default()->RecursivelyCreateDir(dst_dir));
172 std::queue<std::string> dirs_to_copy;
173 dirs_to_copy.push(src_dir);
174 while (!dirs_to_copy.empty()) {
175 const string dir = dirs_to_copy.front();
177 std::vector<std::string> children;
178 TF_ASSERT_OK(Env::Default()->GetChildren(dir, &children));
179 for (
const string& child : children) {
180 const string child_path = io::JoinPath(dir, child);
181 StringPiece remainder = child_path;
182 CHECK(str_util::ConsumePrefix(&remainder, src_dir));
183 if (Env::Default()->IsDirectory(child_path).ok()) {
185 Env::Default()->CreateDir(io::JoinPath(dst_dir, remainder)));
186 dirs_to_copy.push(child_path);
188 TF_ASSERT_OK(Env::Default()->CopyFile(
189 child_path, io::JoinPath(dst_dir, remainder)));