diff options
Diffstat (limited to 'tensorflow/core/platform/cloud/http_request_test.cc')
-rw-r--r-- | tensorflow/core/platform/cloud/http_request_test.cc | 323 |
1 files changed, 323 insertions, 0 deletions
diff --git a/tensorflow/core/platform/cloud/http_request_test.cc b/tensorflow/core/platform/cloud/http_request_test.cc new file mode 100644 index 0000000000..247514c9da --- /dev/null +++ b/tensorflow/core/platform/cloud/http_request_test.cc @@ -0,0 +1,323 @@ +/* Copyright 2016 Google Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/core/platform/cloud/http_request.h" +#include <fstream> +#include "tensorflow/core/lib/core/status_test_util.h" +#include "tensorflow/core/lib/io/path.h" +#include "tensorflow/core/platform/test.h" + +namespace tensorflow { +namespace { + +// A fake proxy that pretends to be libcurl. +class FakeLibCurl : public LibCurl { + public: + FakeLibCurl(const string& response_content, uint64 response_code) + : response_content(response_content), response_code(response_code) {} + Status MaybeLoadDll() override { return Status::OK(); } + CURL* curl_easy_init() override { + is_initialized = true; + // The reuslt just needs to be non-null. + return reinterpret_cast<CURL*>(this); + } + CURLcode curl_easy_setopt(CURL* curl, CURLoption option, + uint64 param) override { + switch (option) { + case CURLOPT_POST: + is_post = param; + break; + default: + break; + } + return CURLE_OK; + } + CURLcode curl_easy_setopt(CURL* curl, CURLoption option, + const char* param) override { + return curl_easy_setopt(curl, option, + reinterpret_cast<void*>(const_cast<char*>(param))); + } + CURLcode curl_easy_setopt(CURL* curl, CURLoption option, + void* param) override { + switch (option) { + case CURLOPT_URL: + url = reinterpret_cast<char*>(param); + break; + case CURLOPT_RANGE: + range = reinterpret_cast<char*>(param); + break; + case CURLOPT_CUSTOMREQUEST: + custom_request = reinterpret_cast<char*>(param); + break; + case CURLOPT_HTTPHEADER: + headers = reinterpret_cast<std::vector<string>*>(param); + break; + case CURLOPT_ERRORBUFFER: + error_buffer = reinterpret_cast<char*>(param); + break; + case CURLOPT_WRITEDATA: + write_data = reinterpret_cast<FILE*>(param); + break; + case CURLOPT_READDATA: + read_data = reinterpret_cast<FILE*>(param); + break; + default: + break; + } + return CURLE_OK; + } + CURLcode curl_easy_setopt(CURL* curl, CURLoption option, + size_t (*param)(void*, size_t, size_t, + FILE*)) override { + EXPECT_EQ(param, &fread) << "Expected the standard fread() function."; + return CURLE_OK; + } + CURLcode curl_easy_setopt(CURL* curl, CURLoption option, + size_t (*param)(const void*, size_t, size_t, + void*)) override { + switch (option) { + case CURLOPT_WRITEFUNCTION: + write_callback = param; + break; + default: + break; + } + return CURLE_OK; + } + CURLcode curl_easy_perform(CURL* curl) override { + if (read_data) { + char buffer[100]; + int bytes_read; + posted_content = ""; + do { + bytes_read = fread(buffer, 1, 100, read_data); + posted_content = + strings::StrCat(posted_content, StringPiece(buffer, bytes_read)); + } while (bytes_read > 0); + } + if (write_data) { + write_callback(response_content.c_str(), 1, response_content.size(), + write_data); + } + return CURLE_OK; + } + CURLcode curl_easy_getinfo(CURL* curl, CURLINFO info, + uint64* value) override { + switch (info) { + case CURLINFO_RESPONSE_CODE: + *value = response_code; + break; + default: + break; + } + return CURLE_OK; + } + CURLcode curl_easy_getinfo(CURL* curl, CURLINFO info, + double* value) override { + switch (info) { + case CURLINFO_SIZE_DOWNLOAD: + *value = response_content.size(); + break; + default: + break; + } + return CURLE_OK; + } + void curl_easy_cleanup(CURL* curl) override { is_cleaned_up = true; } + curl_slist* curl_slist_append(curl_slist* list, const char* str) override { + std::vector<string>* v = list ? reinterpret_cast<std::vector<string>*>(list) + : new std::vector<string>(); + v->push_back(str); + return reinterpret_cast<curl_slist*>(v); + } + void curl_slist_free_all(curl_slist* list) override { + delete reinterpret_cast<std::vector<string>*>(list); + } + + // Variables defining the behavior of this fake. + string response_content; + uint64 response_code; + + // Internal variables to store the libcurl state. + string url; + string range; + string custom_request; + char* error_buffer = nullptr; + bool is_initialized = false; + bool is_cleaned_up = false; + std::vector<string>* headers = nullptr; + FILE* read_data = nullptr; + bool is_post = false; + void* write_data = nullptr; + size_t (*write_callback)(const void* ptr, size_t size, size_t nmemb, + void* userdata) = nullptr; + // Outcome of performing the request. + string posted_content; +}; + +TEST(HttpRequestTest, GetRequest) { + FakeLibCurl* libcurl = new FakeLibCurl("get response", 200); + HttpRequest http_request((std::unique_ptr<LibCurl>(libcurl))); + TF_EXPECT_OK(http_request.Init()); + + char scratch[100] = "random original scratch content"; + StringPiece result = "random original string piece"; + + TF_EXPECT_OK(http_request.SetUri("http://www.testuri.com")); + TF_EXPECT_OK(http_request.AddAuthBearerHeader("fake-bearer")); + TF_EXPECT_OK(http_request.SetRange(100, 199)); + TF_EXPECT_OK(http_request.SetResultBuffer(scratch, 100, &result)); + TF_EXPECT_OK(http_request.Send()); + + EXPECT_EQ("get response", result); + + // Check interactions with libcurl. + EXPECT_TRUE(libcurl->is_initialized); + EXPECT_EQ("http://www.testuri.com", libcurl->url); + EXPECT_EQ("100-199", libcurl->range); + EXPECT_EQ("", libcurl->custom_request); + EXPECT_EQ(1, libcurl->headers->size()); + EXPECT_EQ("Authorization: Bearer fake-bearer", (*libcurl->headers)[0]); + EXPECT_FALSE(libcurl->is_post); +} + +TEST(HttpRequestTest, PostRequest_WithBody) { + FakeLibCurl* libcurl = new FakeLibCurl("", 200); + HttpRequest http_request((std::unique_ptr<LibCurl>(libcurl))); + TF_EXPECT_OK(http_request.Init()); + + auto content_filename = io::JoinPath(testing::TmpDir(), "content"); + std::ofstream content(content_filename, std::ofstream::binary); + content << "post body content"; + content.close(); + + TF_EXPECT_OK(http_request.SetUri("http://www.testuri.com")); + TF_EXPECT_OK(http_request.AddAuthBearerHeader("fake-bearer")); + TF_EXPECT_OK(http_request.SetPostRequest(content_filename)); + TF_EXPECT_OK(http_request.Send()); + + // Check interactions with libcurl. + EXPECT_TRUE(libcurl->is_initialized); + EXPECT_EQ("http://www.testuri.com", libcurl->url); + EXPECT_EQ("", libcurl->custom_request); + EXPECT_EQ(2, libcurl->headers->size()); + EXPECT_EQ("Authorization: Bearer fake-bearer", (*libcurl->headers)[0]); + EXPECT_EQ("Content-Length: 17", (*libcurl->headers)[1]); + EXPECT_TRUE(libcurl->is_post); + EXPECT_EQ("post body content", libcurl->posted_content); + + std::remove(content_filename.c_str()); +} + +TEST(HttpRequestTest, PostRequest_WithoutBody) { + FakeLibCurl* libcurl = new FakeLibCurl("", 200); + HttpRequest http_request((std::unique_ptr<LibCurl>(libcurl))); + TF_EXPECT_OK(http_request.Init()); + + TF_EXPECT_OK(http_request.SetUri("http://www.testuri.com")); + TF_EXPECT_OK(http_request.AddAuthBearerHeader("fake-bearer")); + TF_EXPECT_OK(http_request.SetPostRequest()); + TF_EXPECT_OK(http_request.Send()); + + // Check interactions with libcurl. + EXPECT_TRUE(libcurl->is_initialized); + EXPECT_EQ("http://www.testuri.com", libcurl->url); + EXPECT_EQ("", libcurl->custom_request); + EXPECT_EQ(2, libcurl->headers->size()); + EXPECT_EQ("Authorization: Bearer fake-bearer", (*libcurl->headers)[0]); + EXPECT_EQ("Content-Length: 0", (*libcurl->headers)[1]); + EXPECT_TRUE(libcurl->is_post); + EXPECT_EQ("", libcurl->posted_content); +} + +TEST(HttpRequestTest, DeleteRequest) { + FakeLibCurl* libcurl = new FakeLibCurl("", 200); + HttpRequest http_request((std::unique_ptr<LibCurl>(libcurl))); + TF_EXPECT_OK(http_request.Init()); + + TF_EXPECT_OK(http_request.SetUri("http://www.testuri.com")); + TF_EXPECT_OK(http_request.AddAuthBearerHeader("fake-bearer")); + TF_EXPECT_OK(http_request.SetDeleteRequest()); + TF_EXPECT_OK(http_request.Send()); + + // Check interactions with libcurl. + EXPECT_TRUE(libcurl->is_initialized); + EXPECT_EQ("http://www.testuri.com", libcurl->url); + EXPECT_EQ("DELETE", libcurl->custom_request); + EXPECT_EQ(1, libcurl->headers->size()); + EXPECT_EQ("Authorization: Bearer fake-bearer", (*libcurl->headers)[0]); + EXPECT_FALSE(libcurl->is_post); +} + +TEST(HttpRequestTest, WrongSequenceOfCalls_NoUri) { + FakeLibCurl* libcurl = new FakeLibCurl("", 200); + HttpRequest http_request((std::unique_ptr<LibCurl>(libcurl))); + TF_EXPECT_OK(http_request.Init()); + + auto s = http_request.Send(); + ASSERT_TRUE(errors::IsFailedPrecondition(s)); + EXPECT_TRUE(StringPiece(s.error_message()).contains("URI has not been set")); +} + +TEST(HttpRequestTest, WrongSequenceOfCalls_TwoSends) { + FakeLibCurl* libcurl = new FakeLibCurl("", 200); + HttpRequest http_request((std::unique_ptr<LibCurl>(libcurl))); + TF_EXPECT_OK(http_request.Init()); + + http_request.SetUri("http://www.google.com"); + http_request.Send(); + auto s = http_request.Send(); + ASSERT_TRUE(errors::IsFailedPrecondition(s)); + EXPECT_TRUE(StringPiece(s.error_message()) + .contains("The request has already been sent")); +} + +TEST(HttpRequestTest, WrongSequenceOfCalls_ReusingAfterSend) { + FakeLibCurl* libcurl = new FakeLibCurl("", 200); + HttpRequest http_request((std::unique_ptr<LibCurl>(libcurl))); + TF_EXPECT_OK(http_request.Init()); + + http_request.SetUri("http://www.google.com"); + http_request.Send(); + auto s = http_request.SetUri("http://mail.google.com"); + ASSERT_TRUE(errors::IsFailedPrecondition(s)); + EXPECT_TRUE(StringPiece(s.error_message()) + .contains("The request has already been sent")); +} + +TEST(HttpRequestTest, WrongSequenceOfCalls_SettingMethodTwice) { + FakeLibCurl* libcurl = new FakeLibCurl("", 200); + HttpRequest http_request((std::unique_ptr<LibCurl>(libcurl))); + TF_EXPECT_OK(http_request.Init()); + + http_request.SetDeleteRequest(); + auto s = http_request.SetPostRequest(); + ASSERT_TRUE(errors::IsFailedPrecondition(s)); + EXPECT_TRUE(StringPiece(s.error_message()) + .contains("HTTP method has been already set")); +} + +TEST(HttpRequestTest, WrongSequenceOfCalls_NotInitialized) { + FakeLibCurl* libcurl = new FakeLibCurl("", 200); + HttpRequest http_request((std::unique_ptr<LibCurl>(libcurl))); + + auto s = http_request.SetPostRequest(); + ASSERT_TRUE(errors::IsFailedPrecondition(s)); + EXPECT_TRUE(StringPiece(s.error_message()) + .contains("The object has not been initialized")); +} + +} // namespace +} // namespace tensorflow |