Moved and renamed resource provider manager-related tests. This patch moves the existing `resource_provider_http_api_tests` file to a more general name. We also rename the existing HTTP test. This will allow us to collect most resource provider manager-related unit tests in this file in the future.
Review: https://reviews.apache.org/r/61278/ Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/2c3facbb Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/2c3facbb Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/2c3facbb Branch: refs/heads/master Commit: 2c3facbb62cda6ac4d5266a2677b1347c8cf0fd5 Parents: f9ffc24 Author: Benjamin Bannier <[email protected]> Authored: Fri Aug 18 10:00:25 2017 -0700 Committer: Jie Yu <[email protected]> Committed: Fri Aug 18 11:43:56 2017 -0700 ---------------------------------------------------------------------- src/Makefile.am | 2 +- src/tests/CMakeLists.txt | 2 +- src/tests/resource_provider_http_api_tests.cpp | 299 -------------------- src/tests/resource_provider_manager_tests.cpp | 299 ++++++++++++++++++++ 4 files changed, 301 insertions(+), 301 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/2c3facbb/src/Makefile.am ---------------------------------------------------------------------- diff --git a/src/Makefile.am b/src/Makefile.am index 3db208a..38167a9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2376,7 +2376,7 @@ mesos_tests_SOURCES = \ tests/reservation_endpoints_tests.cpp \ tests/reservation_tests.cpp \ tests/resource_offers_tests.cpp \ - tests/resource_provider_http_api_tests.cpp \ + tests/resource_provider_manager_tests.cpp \ tests/resource_provider_validation_tests.cpp \ tests/resources_tests.cpp \ tests/resources_utils.cpp \ http://git-wip-us.apache.org/repos/asf/mesos/blob/2c3facbb/src/tests/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 6dd2716..6c05ea9 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -115,7 +115,7 @@ set(MESOS_TESTS_SRC protobuf_io_tests.cpp rate_limiting_tests.cpp resource_offers_tests.cpp - resource_provider_http_api_tests.cpp + resource_provider_manager_tests.cpp resource_provider_validation_tests.cpp resources_tests.cpp role_tests.cpp http://git-wip-us.apache.org/repos/asf/mesos/blob/2c3facbb/src/tests/resource_provider_http_api_tests.cpp ---------------------------------------------------------------------- diff --git a/src/tests/resource_provider_http_api_tests.cpp b/src/tests/resource_provider_http_api_tests.cpp deleted file mode 100644 index 85906ea..0000000 --- a/src/tests/resource_provider_http_api_tests.cpp +++ /dev/null @@ -1,299 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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 <string> - -#include <mesos/v1/resource_provider/resource_provider.hpp> - -#include <process/clock.hpp> -#include <process/gmock.hpp> -#include <process/http.hpp> - -#include <stout/lambda.hpp> -#include <stout/protobuf.hpp> -#include <stout/recordio.hpp> -#include <stout/stringify.hpp> - -#include "common/http.hpp" -#include "common/recordio.hpp" - -#include "slave/slave.hpp" - -#include "resource_provider/manager.hpp" - -#include "tests/mesos.hpp" - -namespace http = process::http; - -using mesos::internal::slave::Slave; - -using mesos::master::detector::MasterDetector; - -using mesos::v1::resource_provider::Call; -using mesos::v1::resource_provider::Event; - -using process::Clock; -using process::Future; -using process::Owned; - -using process::http::BadRequest; -using process::http::OK; -using process::http::UnsupportedMediaType; - -using std::string; - -using testing::Values; -using testing::WithParamInterface; - -namespace mesos { -namespace internal { -namespace tests { - -class ResourceProviderHttpApiTest - : public MesosTest, - public WithParamInterface<ContentType> {}; - - -// The tests are parameterized by the content type of the request. -INSTANTIATE_TEST_CASE_P( - ContentType, - ResourceProviderHttpApiTest, - Values(ContentType::PROTOBUF, ContentType::JSON)); - - -TEST_F(ResourceProviderHttpApiTest, NoContentType) -{ - http::Request request; - request.method = "POST"; - request.headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL); - - ResourceProviderManager manager; - - Future<http::Response> response = manager.api(request, None()); - - AWAIT_EXPECT_RESPONSE_STATUS_EQ(BadRequest().status, response); - AWAIT_EXPECT_RESPONSE_BODY_EQ( - "Expecting 'Content-Type' to be present", - response); -} - - -// This test sends a valid JSON blob that cannot be deserialized -// into a valid protobuf resulting in a BadRequest. -TEST_F(ResourceProviderHttpApiTest, ValidJsonButInvalidProtobuf) -{ - JSON::Object object; - object.values["string"] = "valid_json"; - - http::Request request; - request.method = "POST"; - request.headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL); - request.headers["Accept"] = APPLICATION_JSON; - request.headers["Content-Type"] = APPLICATION_JSON; - request.body = stringify(object); - - ResourceProviderManager manager; - - Future<http::Response> response = manager.api(request, None()); - - AWAIT_EXPECT_RESPONSE_STATUS_EQ(BadRequest().status, response); - AWAIT_EXPECT_RESPONSE_BODY_EQ( - "Failed to validate resource_provider::Call: " - "Expecting 'type' to be present", - response); -} - - -TEST_P(ResourceProviderHttpApiTest, MalformedContent) -{ - const ContentType contentType = GetParam(); - - http::Request request; - request.method = "POST"; - request.headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL); - request.headers["Accept"] = stringify(contentType); - request.headers["Content-Type"] = stringify(contentType); - request.body = "MALFORMED_CONTENT"; - - ResourceProviderManager manager; - - Future<http::Response> response = manager.api(request, None()); - - AWAIT_EXPECT_RESPONSE_STATUS_EQ(BadRequest().status, response); - switch (contentType) { - case ContentType::PROTOBUF: - AWAIT_EXPECT_RESPONSE_BODY_EQ( - "Failed to parse body into Call protobuf", - response); - break; - case ContentType::JSON: - AWAIT_EXPECT_RESPONSE_BODY_EQ( - "Failed to parse body into JSON: " - "syntax error at line 1 near: MALFORMED_CONTENT", - response); - break; - case ContentType::RECORDIO: - break; - } -} - - -TEST_P(ResourceProviderHttpApiTest, UnsupportedContentMediaType) -{ - Call call; - call.set_type(Call::SUBSCRIBE); - - Call::Subscribe* subscribe = call.mutable_subscribe(); - - mesos::v1::ResourceProviderInfo* info = - subscribe->mutable_resource_provider_info(); - - info->set_type("org.apache.mesos.rp.test"); - info->set_name("test"); - - const ContentType contentType = GetParam(); - const string unknownMediaType = "application/unknown-media-type"; - - http::Request request; - request.method = "POST"; - request.headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL); - request.headers["Accept"] = stringify(contentType); - request.headers["Content-Type"] = unknownMediaType; - request.body = serialize(contentType, call); - - ResourceProviderManager manager; - - Future<http::Response> response = manager.api(request, None()); - - AWAIT_EXPECT_RESPONSE_STATUS_EQ(UnsupportedMediaType().status, response) - << response->body; -} - - -TEST_P(ResourceProviderHttpApiTest, Subscribe) -{ - Call call; - call.set_type(Call::SUBSCRIBE); - - Call::Subscribe* subscribe = call.mutable_subscribe(); - - mesos::v1::ResourceProviderInfo* info = - subscribe->mutable_resource_provider_info(); - - info->set_type("org.apache.mesos.rp.test"); - info->set_name("test"); - - const ContentType contentType = GetParam(); - - http::Request request; - request.method = "POST"; - request.headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL); - request.headers["Accept"] = stringify(contentType); - request.headers["Content-Type"] = stringify(contentType); - request.body = serialize(contentType, call); - - ResourceProviderManager manager; - - Future<http::Response> response = manager.api(request, None()); - - AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response) << response->body; - ASSERT_EQ(http::Response::PIPE, response->type); - - Option<http::Pipe::Reader> reader = response->reader; - ASSERT_SOME(reader); - - recordio::Reader<Event> responseDecoder( - ::recordio::Decoder<Event>( - lambda::bind(deserialize<Event>, contentType, lambda::_1)), - reader.get()); - - Future<Result<Event>> event = responseDecoder.read(); - AWAIT_READY(event); - ASSERT_SOME(event.get()); - - // Check event type is subscribed and the resource provider id is set. - ASSERT_EQ(Event::SUBSCRIBED, event->get().type()); - ASSERT_NE("", event->get().subscribed().provider_id().value()); -} - - -// This test starts an agent and connects directly with its resource -// provider endpoint. -TEST_P(ResourceProviderHttpApiTest, AgentEndpoint) -{ - Try<Owned<cluster::Master>> master = StartMaster(); - ASSERT_SOME(master); - - Future<Nothing> __recover = FUTURE_DISPATCH(_, &Slave::__recover); - - Owned<MasterDetector> detector = master.get()->createDetector(); - - Try<Owned<cluster::Slave>> agent = StartSlave(detector.get()); - ASSERT_SOME(agent); - - AWAIT_READY(__recover); - - // Wait for recovery to be complete. - Clock::pause(); - Clock::settle(); - - Call call; - call.set_type(Call::SUBSCRIBE); - - Call::Subscribe* subscribe = call.mutable_subscribe(); - - mesos::v1::ResourceProviderInfo* info = - subscribe->mutable_resource_provider_info(); - - info->set_type("org.apache.mesos.rp.test"); - info->set_name("test"); - - const ContentType contentType = GetParam(); - - http::Headers headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL); - headers["Accept"] = stringify(contentType); - - Future<http::Response> response = http::streaming::post( - agent.get()->pid, - "api/v1/resource_provider", - headers, - serialize(contentType, call), - stringify(contentType)); - - AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response); - AWAIT_EXPECT_RESPONSE_HEADER_EQ("chunked", "Transfer-Encoding", response); - ASSERT_EQ(http::Response::PIPE, response->type); - - Option<http::Pipe::Reader> reader = response->reader; - ASSERT_SOME(reader); - - recordio::Reader<Event> responseDecoder( - ::recordio::Decoder<Event>( - lambda::bind(deserialize<Event>, contentType, lambda::_1)), - reader.get()); - - Future<Result<Event>> event = responseDecoder.read(); - AWAIT_READY(event); - ASSERT_SOME(event.get()); - - // Check event type is subscribed and the resource provider id is set. - ASSERT_EQ(Event::SUBSCRIBED, event->get().type()); - ASSERT_NE("", event->get().subscribed().provider_id().value()); -} - -} // namespace tests { -} // namespace internal { -} // namespace mesos { http://git-wip-us.apache.org/repos/asf/mesos/blob/2c3facbb/src/tests/resource_provider_manager_tests.cpp ---------------------------------------------------------------------- diff --git a/src/tests/resource_provider_manager_tests.cpp b/src/tests/resource_provider_manager_tests.cpp new file mode 100644 index 0000000..83a1340 --- /dev/null +++ b/src/tests/resource_provider_manager_tests.cpp @@ -0,0 +1,299 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 <string> + +#include <mesos/v1/resource_provider/resource_provider.hpp> + +#include <process/clock.hpp> +#include <process/gmock.hpp> +#include <process/http.hpp> + +#include <stout/lambda.hpp> +#include <stout/protobuf.hpp> +#include <stout/recordio.hpp> +#include <stout/stringify.hpp> + +#include "common/http.hpp" +#include "common/recordio.hpp" + +#include "slave/slave.hpp" + +#include "resource_provider/manager.hpp" + +#include "tests/mesos.hpp" + +namespace http = process::http; + +using mesos::internal::slave::Slave; + +using mesos::master::detector::MasterDetector; + +using mesos::v1::resource_provider::Call; +using mesos::v1::resource_provider::Event; + +using process::Clock; +using process::Future; +using process::Owned; + +using process::http::BadRequest; +using process::http::OK; +using process::http::UnsupportedMediaType; + +using std::string; + +using testing::Values; +using testing::WithParamInterface; + +namespace mesos { +namespace internal { +namespace tests { + +class ResourceProviderManagerHttpApiTest + : public MesosTest, + public WithParamInterface<ContentType> {}; + + +// The tests are parameterized by the content type of the request. +INSTANTIATE_TEST_CASE_P( + ContentType, + ResourceProviderManagerHttpApiTest, + Values(ContentType::PROTOBUF, ContentType::JSON)); + + +TEST_F(ResourceProviderManagerHttpApiTest, NoContentType) +{ + http::Request request; + request.method = "POST"; + request.headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL); + + ResourceProviderManager manager; + + Future<http::Response> response = manager.api(request, None()); + + AWAIT_EXPECT_RESPONSE_STATUS_EQ(BadRequest().status, response); + AWAIT_EXPECT_RESPONSE_BODY_EQ( + "Expecting 'Content-Type' to be present", + response); +} + + +// This test sends a valid JSON blob that cannot be deserialized +// into a valid protobuf resulting in a BadRequest. +TEST_F(ResourceProviderManagerHttpApiTest, ValidJsonButInvalidProtobuf) +{ + JSON::Object object; + object.values["string"] = "valid_json"; + + http::Request request; + request.method = "POST"; + request.headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL); + request.headers["Accept"] = APPLICATION_JSON; + request.headers["Content-Type"] = APPLICATION_JSON; + request.body = stringify(object); + + ResourceProviderManager manager; + + Future<http::Response> response = manager.api(request, None()); + + AWAIT_EXPECT_RESPONSE_STATUS_EQ(BadRequest().status, response); + AWAIT_EXPECT_RESPONSE_BODY_EQ( + "Failed to validate resource_provider::Call: " + "Expecting 'type' to be present", + response); +} + + +TEST_P(ResourceProviderManagerHttpApiTest, MalformedContent) +{ + const ContentType contentType = GetParam(); + + http::Request request; + request.method = "POST"; + request.headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL); + request.headers["Accept"] = stringify(contentType); + request.headers["Content-Type"] = stringify(contentType); + request.body = "MALFORMED_CONTENT"; + + ResourceProviderManager manager; + + Future<http::Response> response = manager.api(request, None()); + + AWAIT_EXPECT_RESPONSE_STATUS_EQ(BadRequest().status, response); + switch (contentType) { + case ContentType::PROTOBUF: + AWAIT_EXPECT_RESPONSE_BODY_EQ( + "Failed to parse body into Call protobuf", + response); + break; + case ContentType::JSON: + AWAIT_EXPECT_RESPONSE_BODY_EQ( + "Failed to parse body into JSON: " + "syntax error at line 1 near: MALFORMED_CONTENT", + response); + break; + case ContentType::RECORDIO: + break; + } +} + + +TEST_P(ResourceProviderManagerHttpApiTest, UnsupportedContentMediaType) +{ + Call call; + call.set_type(Call::SUBSCRIBE); + + Call::Subscribe* subscribe = call.mutable_subscribe(); + + mesos::v1::ResourceProviderInfo* info = + subscribe->mutable_resource_provider_info(); + + info->set_type("org.apache.mesos.rp.test"); + info->set_name("test"); + + const ContentType contentType = GetParam(); + const string unknownMediaType = "application/unknown-media-type"; + + http::Request request; + request.method = "POST"; + request.headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL); + request.headers["Accept"] = stringify(contentType); + request.headers["Content-Type"] = unknownMediaType; + request.body = serialize(contentType, call); + + ResourceProviderManager manager; + + Future<http::Response> response = manager.api(request, None()); + + AWAIT_EXPECT_RESPONSE_STATUS_EQ(UnsupportedMediaType().status, response) + << response->body; +} + + +TEST_P(ResourceProviderManagerHttpApiTest, Subscribe) +{ + Call call; + call.set_type(Call::SUBSCRIBE); + + Call::Subscribe* subscribe = call.mutable_subscribe(); + + mesos::v1::ResourceProviderInfo* info = + subscribe->mutable_resource_provider_info(); + + info->set_type("org.apache.mesos.rp.test"); + info->set_name("test"); + + const ContentType contentType = GetParam(); + + http::Request request; + request.method = "POST"; + request.headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL); + request.headers["Accept"] = stringify(contentType); + request.headers["Content-Type"] = stringify(contentType); + request.body = serialize(contentType, call); + + ResourceProviderManager manager; + + Future<http::Response> response = manager.api(request, None()); + + AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response) << response->body; + ASSERT_EQ(http::Response::PIPE, response->type); + + Option<http::Pipe::Reader> reader = response->reader; + ASSERT_SOME(reader); + + recordio::Reader<Event> responseDecoder( + ::recordio::Decoder<Event>( + lambda::bind(deserialize<Event>, contentType, lambda::_1)), + reader.get()); + + Future<Result<Event>> event = responseDecoder.read(); + AWAIT_READY(event); + ASSERT_SOME(event.get()); + + // Check event type is subscribed and the resource provider id is set. + ASSERT_EQ(Event::SUBSCRIBED, event->get().type()); + ASSERT_NE("", event->get().subscribed().provider_id().value()); +} + + +// This test starts an agent and connects directly with its resource +// provider endpoint. +TEST_P(ResourceProviderManagerHttpApiTest, AgentEndpoint) +{ + Try<Owned<cluster::Master>> master = StartMaster(); + ASSERT_SOME(master); + + Future<Nothing> __recover = FUTURE_DISPATCH(_, &Slave::__recover); + + Owned<MasterDetector> detector = master.get()->createDetector(); + + Try<Owned<cluster::Slave>> agent = StartSlave(detector.get()); + ASSERT_SOME(agent); + + AWAIT_READY(__recover); + + // Wait for recovery to be complete. + Clock::pause(); + Clock::settle(); + + Call call; + call.set_type(Call::SUBSCRIBE); + + Call::Subscribe* subscribe = call.mutable_subscribe(); + + mesos::v1::ResourceProviderInfo* info = + subscribe->mutable_resource_provider_info(); + + info->set_type("org.apache.mesos.rp.test"); + info->set_name("test"); + + const ContentType contentType = GetParam(); + + http::Headers headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL); + headers["Accept"] = stringify(contentType); + + Future<http::Response> response = http::streaming::post( + agent.get()->pid, + "api/v1/resource_provider", + headers, + serialize(contentType, call), + stringify(contentType)); + + AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response); + AWAIT_EXPECT_RESPONSE_HEADER_EQ("chunked", "Transfer-Encoding", response); + ASSERT_EQ(http::Response::PIPE, response->type); + + Option<http::Pipe::Reader> reader = response->reader; + ASSERT_SOME(reader); + + recordio::Reader<Event> responseDecoder( + ::recordio::Decoder<Event>( + lambda::bind(deserialize<Event>, contentType, lambda::_1)), + reader.get()); + + Future<Result<Event>> event = responseDecoder.read(); + AWAIT_READY(event); + ASSERT_SOME(event.get()); + + // Check event type is subscribed and the resource provider id is set. + ASSERT_EQ(Event::SUBSCRIBED, event->get().type()); + ASSERT_NE("", event->get().subscribed().provider_id().value()); +} + +} // namespace tests { +} // namespace internal { +} // namespace mesos {
