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 {