You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by vi...@apache.org on 2017/03/15 18:36:16 UTC
[3/3] mesos git commit: Added a test for the 'CombinedAuthenticator'.
Added a test for the 'CombinedAuthenticator'.
This patch adds a unit test to verify the functionality of
the `CombinedAuthenticator`. The new test is called
`CombinedAuthenticatorTest.MultipleAuthenticators`.
Review: https://reviews.apache.org/r/56475/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/a68e1f28
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/a68e1f28
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/a68e1f28
Branch: refs/heads/master
Commit: a68e1f28d92e2f9b0c1ea3a6701b041709aaad8a
Parents: af5af3f
Author: Greg Mann <gr...@mesosphere.io>
Authored: Wed Mar 15 19:36:01 2017 +0100
Committer: Vinod Kone <vi...@gmail.com>
Committed: Wed Mar 15 19:36:01 2017 +0100
----------------------------------------------------------------------
src/tests/http_authentication_tests.cpp | 306 ++++++++++++++++++++++++++-
1 file changed, 303 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/a68e1f28/src/tests/http_authentication_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/http_authentication_tests.cpp b/src/tests/http_authentication_tests.cpp
index 0eeed9d..36d2b73 100644
--- a/src/tests/http_authentication_tests.cpp
+++ b/src/tests/http_authentication_tests.cpp
@@ -19,6 +19,7 @@
#include <vector>
#include <mesos/authentication/http/basic_authenticator_factory.hpp>
+#include <mesos/authentication/http/combined_authenticator.hpp>
#include <mesos/module/http_authenticator.hpp>
@@ -33,6 +34,7 @@
using namespace process;
+using std::string;
using std::vector;
namespace process {
@@ -52,6 +54,27 @@ bool operator==(const Unauthorized &left, const Unauthorized &right)
}
+bool operator==(const URL &left, const URL &right)
+{
+ return left.scheme == right.scheme &&
+ left.domain == right.domain &&
+ left.ip == right.ip &&
+ left.path == right.path &&
+ left.query == right.query &&
+ left.fragment == right.fragment &&
+ left.port == right.port;
+}
+
+
+bool operator==(const Request &left, const Request &right)
+{
+ return left.headers == right.headers &&
+ left.url == right.url &&
+ left.method == right.method &&
+ left.body == right.body;
+}
+
+
namespace authentication {
bool operator==(
@@ -73,19 +96,21 @@ namespace internal {
namespace tests {
using mesos::http::authentication::BasicAuthenticatorFactory;
+using mesos::http::authentication::CombinedAuthenticator;
+using process::http::Forbidden;
using process::http::Request;
using process::http::Unauthorized;
using process::http::authentication::Authenticator;
-using process::http::authentication::Principal;
using process::http::authentication::AuthenticationResult;
+using process::http::authentication::Principal;
-static const std::string REALM = "tatooine";
+static const string REALM = "tatooine";
static Parameters createBasicAuthenticatorParameters(
- const Option<std::string>& realm,
+ const Option<string>& realm,
const Option<Credentials>& credentials)
{
Parameters parameters;
@@ -235,6 +260,281 @@ TYPED_TEST(HttpAuthenticationTest, BasicWithoutRealm)
ASSERT_ERROR(create);
}
+
+class MockAuthenticator : public Authenticator
+{
+public:
+ MockAuthenticator(string scheme) : mockScheme(scheme) {}
+
+ MockAuthenticator(const MockAuthenticator& authenticator)
+ : mockScheme(authenticator.mockScheme) {}
+
+ MOCK_METHOD1(authenticate, Future<AuthenticationResult>(const Request&));
+
+ virtual string scheme() const { return mockScheme; }
+
+private:
+ const string mockScheme;
+};
+
+
+AuthenticationResult createUnauthorized(MockAuthenticator& authenticator)
+{
+ AuthenticationResult result;
+ result.unauthorized = Unauthorized(
+ {authenticator.scheme() + " realm=\"" + REALM + "\""},
+ authenticator.scheme() + " unauthorized");
+
+ return result;
+}
+
+
+AuthenticationResult createForbidden(MockAuthenticator& authenticator)
+{
+ AuthenticationResult result;
+ result.forbidden = Forbidden(authenticator.scheme() + " forbidden");
+
+ return result;
+}
+
+
+AuthenticationResult createCombinedUnauthorized(
+ vector<MockAuthenticator> authenticators)
+{
+ AuthenticationResult result;
+ vector<string> headers;
+ vector<string> bodies;
+
+ foreach (const MockAuthenticator& authenticator, authenticators) {
+ headers.push_back(authenticator.scheme() + " realm=\"" + REALM + "\"");
+ bodies.push_back(
+ "\"" + authenticator.scheme() + "\" authenticator returned:\n" +
+ authenticator.scheme() + " unauthorized");
+ }
+
+ result.unauthorized = Unauthorized(
+ {strings::join(",", headers)},
+ strings::join("\n\n", bodies));
+
+ return result;
+}
+
+
+AuthenticationResult createCombinedForbidden(
+ vector<MockAuthenticator> authenticators)
+{
+ AuthenticationResult result;
+ vector<string> bodies;
+
+ foreach (const MockAuthenticator& authenticator, authenticators) {
+ bodies.push_back(
+ "\"" + authenticator.scheme() + "\" authenticator returned:\n" +
+ authenticator.scheme() + " forbidden");
+ }
+
+ result.forbidden = Forbidden(strings::join("\n\n", bodies));
+
+ return result;
+}
+
+
+// Verifies the functionality of the `CombinedAuthenticator`.
+//
+// Note: This test relies on the order of invocation of the installed
+// authenticators. If the `CombinedAuthenticator` is changed in the future to
+// call them in a different order, this test must be udpated.
+TEST(CombinedAuthenticatorTest, MultipleAuthenticators)
+{
+ // Create two mock HTTP authenticators to install.
+ MockAuthenticator* basicAuthenticator = new MockAuthenticator("Basic");
+ MockAuthenticator* bearerAuthenticator = new MockAuthenticator("Bearer");
+
+ // Create a `CombinedAuthenticator` containing multiple authenticators.
+ Owned<Authenticator> combinedAuthenticator(
+ new CombinedAuthenticator(
+ REALM,
+ {
+ Owned<Authenticator>(basicAuthenticator),
+ Owned<Authenticator>(bearerAuthenticator)
+ }
+ ));
+
+ Request request;
+ request.headers.put(
+ "Authorization",
+ "Basic " + base64::encode("user:password"));
+
+ // The first authenticator succeeds.
+ {
+ AuthenticationResult successfulResult;
+ successfulResult.principal = Principal("user");
+
+ EXPECT_CALL(*basicAuthenticator, authenticate(request))
+ .WillOnce(Return(successfulResult));
+
+ Future<AuthenticationResult> result =
+ combinedAuthenticator->authenticate(request);
+ AWAIT_EXPECT_EQ(successfulResult, result);
+ }
+
+ // The first authenticator fails but the second one succeeds.
+ {
+ AuthenticationResult successfulResult;
+ successfulResult.principal = Principal("user");
+
+ EXPECT_CALL(*basicAuthenticator, authenticate(request))
+ .WillOnce(Return(createUnauthorized(*basicAuthenticator)));
+ EXPECT_CALL(*bearerAuthenticator, authenticate(request))
+ .WillOnce(Return(successfulResult));
+
+ Future<AuthenticationResult> result =
+ combinedAuthenticator->authenticate(request);
+ AWAIT_EXPECT_EQ(successfulResult, result);
+ }
+
+ // Two Unauthorized results.
+ {
+ EXPECT_CALL(*basicAuthenticator, authenticate(request))
+ .WillOnce(Return(createUnauthorized(*basicAuthenticator)));
+ EXPECT_CALL(*bearerAuthenticator, authenticate(request))
+ .WillOnce(Return(createUnauthorized(*bearerAuthenticator)));
+
+ Future<AuthenticationResult> result =
+ combinedAuthenticator->authenticate(request);
+ AWAIT_EXPECT_EQ(
+ createCombinedUnauthorized({*basicAuthenticator, *bearerAuthenticator}),
+ result);
+ }
+
+ // One Unauthorized and one Forbidden result.
+ {
+ EXPECT_CALL(*basicAuthenticator, authenticate(request))
+ .WillOnce(Return(createUnauthorized(*basicAuthenticator)));
+ EXPECT_CALL(*bearerAuthenticator, authenticate(request))
+ .WillOnce(Return(createForbidden(*bearerAuthenticator)));
+
+ Future<AuthenticationResult> result =
+ combinedAuthenticator->authenticate(request);
+ AWAIT_EXPECT_EQ(createCombinedUnauthorized({*basicAuthenticator}), result);
+ }
+
+ // Two Forbidden results.
+ {
+ EXPECT_CALL(*basicAuthenticator, authenticate(request))
+ .WillOnce(Return(createForbidden(*basicAuthenticator)));
+ EXPECT_CALL(*bearerAuthenticator, authenticate(request))
+ .WillOnce(Return(createForbidden(*bearerAuthenticator)));
+
+ Future<AuthenticationResult> result =
+ combinedAuthenticator->authenticate(request);
+ AWAIT_EXPECT_EQ(
+ createCombinedForbidden({*basicAuthenticator, *bearerAuthenticator}),
+ result);
+ }
+
+ // Two empty results.
+ {
+ AuthenticationResult emptyResult;
+
+ EXPECT_CALL(*basicAuthenticator, authenticate(request))
+ .WillOnce(Return(emptyResult));
+ EXPECT_CALL(*bearerAuthenticator, authenticate(request))
+ .WillOnce(Return(emptyResult));
+
+ Future<AuthenticationResult> result =
+ combinedAuthenticator->authenticate(request);
+ AWAIT_EXPECT_EQ(emptyResult, result);
+ }
+
+ // One empty and one Unauthorized result.
+ {
+ AuthenticationResult emptyResult;
+
+ EXPECT_CALL(*basicAuthenticator, authenticate(request))
+ .WillOnce(Return(emptyResult));
+ EXPECT_CALL(*bearerAuthenticator, authenticate(request))
+ .WillOnce(Return(createUnauthorized(*bearerAuthenticator)));
+
+ Future<AuthenticationResult> result =
+ combinedAuthenticator->authenticate(request);
+ AWAIT_EXPECT_EQ(createCombinedUnauthorized({*bearerAuthenticator}), result);
+ }
+
+ // One empty and one successful result.
+ {
+ AuthenticationResult emptyResult;
+ AuthenticationResult successfulResult;
+ successfulResult.principal = Principal("user");
+
+ EXPECT_CALL(*basicAuthenticator, authenticate(request))
+ .WillOnce(Return(emptyResult));
+ EXPECT_CALL(*bearerAuthenticator, authenticate(request))
+ .WillOnce(Return(successfulResult));
+
+ Future<AuthenticationResult> result =
+ combinedAuthenticator->authenticate(request);
+ AWAIT_EXPECT_EQ(successfulResult, result);
+ }
+
+ // Two failed futures.
+ {
+ Future<AuthenticationResult> failedResult(Failure("Failed result"));
+
+ EXPECT_CALL(*basicAuthenticator, authenticate(request))
+ .WillOnce(Return(failedResult));
+ EXPECT_CALL(*bearerAuthenticator, authenticate(request))
+ .WillOnce(Return(failedResult));
+
+ Future<AuthenticationResult> result =
+ combinedAuthenticator->authenticate(request);
+ AWAIT_EXPECT_FAILED(result);
+ }
+
+ // One failed future and one Unauthorized result.
+ {
+ Future<AuthenticationResult> failedResult(Failure("Failed result"));
+
+ EXPECT_CALL(*basicAuthenticator, authenticate(request))
+ .WillOnce(Return(failedResult));
+ EXPECT_CALL(*bearerAuthenticator, authenticate(request))
+ .WillOnce(Return(createUnauthorized(*bearerAuthenticator)));
+
+ Future<AuthenticationResult> result =
+ combinedAuthenticator->authenticate(request);
+ AWAIT_EXPECT_EQ(createCombinedUnauthorized({*bearerAuthenticator}), result);
+ }
+
+ // One failed future and one Forbidden result.
+ {
+ Future<AuthenticationResult> failedResult(Failure("Failed result"));
+
+ EXPECT_CALL(*basicAuthenticator, authenticate(request))
+ .WillOnce(Return(failedResult));
+ EXPECT_CALL(*bearerAuthenticator, authenticate(request))
+ .WillOnce(Return(createForbidden(*bearerAuthenticator)));
+
+ Future<AuthenticationResult> result =
+ combinedAuthenticator->authenticate(request);
+ AWAIT_EXPECT_EQ(createCombinedForbidden({*bearerAuthenticator}), result);
+ }
+
+ // One failed future and one successful result.
+ {
+ Future<AuthenticationResult> failedResult(Failure("Failed result"));
+ AuthenticationResult successfulResult;
+ successfulResult.principal = Principal("user");
+
+ EXPECT_CALL(*basicAuthenticator, authenticate(request))
+ .WillOnce(Return(failedResult));
+ EXPECT_CALL(*bearerAuthenticator, authenticate(request))
+ .WillOnce(Return(successfulResult));
+
+ Future<AuthenticationResult> result =
+ combinedAuthenticator->authenticate(request);
+ AWAIT_EXPECT_EQ(successfulResult, result);
+ }
+}
+
} // namespace tests {
} // namespace internal {
} // namespace mesos {