TensorFlow Serving C++ API Documentation
http_rest_api_util_test.cc
1 /* Copyright 2021 Google Inc. 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_serving/model_servers/http_rest_api_util.h"
17 
18 #include <limits>
19 
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22 #include "tensorflow/core/lib/core/status_test_util.h"
23 #include "tensorflow_serving/test_util/test_util.h"
24 
25 namespace tensorflow {
26 namespace serving {
27 namespace {
28 
29 using ::testing::HasSubstr;
30 
31 class HttpRestApiUtilTest : public ::testing::Test {};
32 
33 TEST_F(HttpRestApiUtilTest, TestParseModelInfoForGet) {
34  string model_name;
35  absl::optional<int64_t> model_version;
36  absl::optional<string> model_version_label;
37  string method;
38  string model_subresource;
39  bool parse_successful;
40 
41  // Test reserved charactors in model name.
42  const absl::string_view request_path_1 =
43  "/v1/models/"
44  "modelname%21%23%24%25%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D";
45  TF_EXPECT_OK(ParseModelInfo("GET", request_path_1, &model_name,
46  &model_version, &model_version_label, &method,
47  &model_subresource, &parse_successful));
48  EXPECT_EQ(model_name, "modelname!#$%&'()*+,/:;=?@[]");
49  EXPECT_TRUE(parse_successful);
50 
51  // Test model version.
52  const absl::string_view request_path_2 = "/v1/models/modelname/versions/99";
53  TF_EXPECT_OK(ParseModelInfo("GET", request_path_2, &model_name,
54  &model_version, &model_version_label, &method,
55  &model_subresource, &parse_successful));
56  EXPECT_EQ(model_name, "modelname");
57  EXPECT_EQ(model_version.value(), 99);
58  EXPECT_TRUE(parse_successful);
59 
60  // Test labels.
61  const absl::string_view request_path_3 = "/v1/models/modelname/labels/latest";
62  TF_EXPECT_OK(ParseModelInfo("GET", request_path_3, &model_name,
63  &model_version, &model_version_label, &method,
64  &model_subresource, &parse_successful));
65  EXPECT_EQ(model_name, "modelname");
66  EXPECT_EQ(model_version_label.value(), "latest");
67  EXPECT_TRUE(parse_successful);
68 
69  // Test labels with reserved charactors.
70  const absl::string_view request_path_4 =
71  "/v1/models/modelname/labels/"
72  "latest%21%23%24%25%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D";
73  TF_EXPECT_OK(ParseModelInfo("GET", request_path_4, &model_name,
74  &model_version, &model_version_label, &method,
75  &model_subresource, &parse_successful));
76  EXPECT_EQ(model_name, "modelname");
77  EXPECT_EQ(model_version_label.value(), "latest!#$%&'()*+,/:;=?@[]");
78  EXPECT_TRUE(parse_successful);
79 
80  // Test metadata.
81  const absl::string_view request_path_5 =
82  "/v1/models/modelname/labels/latest/metadata";
83  TF_EXPECT_OK(ParseModelInfo("GET", request_path_5, &model_name,
84  &model_version, &model_version_label, &method,
85  &model_subresource, &parse_successful));
86  EXPECT_EQ(model_name, "modelname");
87  EXPECT_EQ(model_version_label.value(), "latest");
88  EXPECT_EQ(model_subresource, "metadata");
89  EXPECT_TRUE(parse_successful);
90 
91  // Test metadata with reserved charactors.
92  const absl::string_view request_path_6 =
93  "/v1/models/"
94  "modelname%21%23%24%25%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D/"
95  "labels/latest%21%23%24%25%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D/"
96  "metadata";
97  TF_EXPECT_OK(ParseModelInfo("GET", request_path_6, &model_name,
98  &model_version, &model_version_label, &method,
99  &model_subresource, &parse_successful));
100  EXPECT_EQ(model_name, "modelname!#$%&'()*+,/:;=?@[]");
101  EXPECT_EQ(model_version_label.value(), "latest!#$%&'()*+,/:;=?@[]");
102  EXPECT_EQ(model_subresource, "metadata");
103  EXPECT_TRUE(parse_successful);
104 
105  // Test failure cases.
106  TF_EXPECT_OK(ParseModelInfo("GET", "/v1/foo", &model_name, &model_version,
107  &model_version_label, &method, &model_subresource,
108  &parse_successful));
109  EXPECT_FALSE(parse_successful);
110  TF_EXPECT_OK(ParseModelInfo("GET", "/v1/models/foo:predict", &model_name,
111  &model_version, &model_version_label, &method,
112  &model_subresource, &parse_successful));
113  EXPECT_FALSE(parse_successful);
114  TF_EXPECT_OK(ParseModelInfo("GET", "/v1/models/foo/version/50:predict",
115  &model_name, &model_version, &model_version_label,
116  &method, &model_subresource, &parse_successful));
117  EXPECT_FALSE(parse_successful);
118 }
119 
120 TEST_F(HttpRestApiUtilTest, TestParseModelInfoForPost) {
121  string model_name;
122  absl::optional<int64_t> model_version;
123  absl::optional<string> model_version_label;
124  string method;
125  string model_subresource;
126  bool parse_successful;
127 
128  // Test reserved charactors in model name.
129  const absl::string_view request_path_1 =
130  "/v1/models/"
131  "modelname%21%23%24%25%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D:"
132  "predict";
133  TF_EXPECT_OK(ParseModelInfo("POST", request_path_1, &model_name,
134  &model_version, &model_version_label, &method,
135  &model_subresource, &parse_successful));
136  EXPECT_EQ(model_name, "modelname!#$%&'()*+,/:;=?@[]");
137  EXPECT_EQ(method, "predict");
138  EXPECT_TRUE(parse_successful);
139 
140  // Test model version.
141  const absl::string_view request_path_2 =
142  "/v1/models/modelname/versions/99:predict";
143  TF_EXPECT_OK(ParseModelInfo("POST", request_path_2, &model_name,
144  &model_version, &model_version_label, &method,
145  &model_subresource, &parse_successful));
146  EXPECT_EQ(model_name, "modelname");
147  EXPECT_EQ(model_version.value(), 99);
148  EXPECT_EQ(method, "predict");
149  EXPECT_TRUE(parse_successful);
150 
151  // Test labels.
152  const absl::string_view request_path_3 =
153  "/v1/models/modelname/labels/latest:predict";
154  TF_EXPECT_OK(ParseModelInfo("POST", request_path_3, &model_name,
155  &model_version, &model_version_label, &method,
156  &model_subresource, &parse_successful));
157  EXPECT_EQ(model_name, "modelname");
158  EXPECT_EQ(model_version_label.value(), "latest");
159  EXPECT_EQ(method, "predict");
160  EXPECT_TRUE(parse_successful);
161 
162  // Test labels with reserved charactors.
163  const absl::string_view request_path_4 =
164  "/v1/models/modelname/labels/"
165  "latest%21%23%24%25%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D:predict";
166  TF_EXPECT_OK(ParseModelInfo("POST", request_path_4, &model_name,
167  &model_version, &model_version_label, &method,
168  &model_subresource, &parse_successful));
169  EXPECT_EQ(model_name, "modelname");
170  EXPECT_EQ(model_version_label.value(), "latest!#$%&'()*+,/:;=?@[]");
171  EXPECT_EQ(method, "predict");
172  EXPECT_TRUE(parse_successful);
173 
174  // Test reserved charactors in labels and model name.
175  const absl::string_view request_path_6 =
176  "/v1/models/"
177  "modelname%21%23%24%25%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D/"
178  "labels/"
179  "latest%21%23%24%25%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D:predict";
180  TF_EXPECT_OK(ParseModelInfo("POST", request_path_6, &model_name,
181  &model_version, &model_version_label, &method,
182  &model_subresource, &parse_successful));
183  EXPECT_EQ(model_name, "modelname!#$%&'()*+,/:;=?@[]");
184  EXPECT_EQ(model_version_label.value(), "latest!#$%&'()*+,/:;=?@[]");
185  EXPECT_EQ(method, "predict");
186  EXPECT_TRUE(parse_successful);
187 
188  // Test failure cases.
189  TF_EXPECT_OK(ParseModelInfo("POST", "/v1/foo", &model_name, &model_version,
190  &model_version_label, &method, &model_subresource,
191  &parse_successful));
192  EXPECT_FALSE(parse_successful);
193  TF_EXPECT_OK(ParseModelInfo("POST", "/v1/models", &model_name, &model_version,
194  &model_version_label, &method, &model_subresource,
195  &parse_successful));
196  EXPECT_FALSE(parse_successful);
197  TF_EXPECT_OK(ParseModelInfo("POST", "/v1/models/foo/version/50:predict",
198  &model_name, &model_version, &model_version_label,
199  &method, &model_subresource, &parse_successful));
200  EXPECT_FALSE(parse_successful);
201  TF_EXPECT_OK(ParseModelInfo("POST", "/v1/models/foo/versions/string:predict",
202  &model_name, &model_version, &model_version_label,
203  &method, &model_subresource, &parse_successful));
204  EXPECT_FALSE(parse_successful);
205  auto status = ParseModelInfo(
206  "POST",
207  absl::StrCat("/v1/models/foo/versions/",
208  std::numeric_limits<uint64_t>::max(), ":predict"),
209  &model_name, &model_version, &model_version_label, &method,
210  &model_subresource, &parse_successful);
211  EXPECT_TRUE(parse_successful);
212  EXPECT_TRUE(errors::IsInvalidArgument(status));
213  EXPECT_THAT(status.message(), HasSubstr("Failed to convert version"));
214  TF_EXPECT_OK(ParseModelInfo("POST", "/v1/models/foo/metadata", &model_name,
215  &model_version, &model_version_label, &method,
216  &model_subresource, &parse_successful));
217  EXPECT_FALSE(parse_successful);
218  TF_EXPECT_OK(ParseModelInfo(
219  "POST", "/v1/models/foo/versions/50/labels/some_label:regress",
220  &model_name, &model_version, &model_version_label, &method,
221  &model_subresource, &parse_successful));
222  EXPECT_FALSE(parse_successful);
223 }
224 } // namespace
225 } // namespace serving
226 } // namespace tensorflow