blob: 1f4470b2384f4d591bbc05515e0101129c68b668 [file] [log] [blame]
// 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 <iostream>
#include <glog/logging.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <process/gmock.hpp>
#include <process/gtest.hpp>
#include <process/socket.hpp>
#include <process/ssl/flags.hpp>
#include <stout/gtest.hpp>
#include <stout/try.hpp>
#include "openssl.hpp"
namespace network = process::network;
namespace openssl = network::openssl;
using network::inet::Address;
using network::inet::Socket;
using network::internal::SocketImpl;
using process::Future;
using std::cout;
using std::endl;
using std::string;
// We only run these tests if we have configured with '--enable-ssl'.
#ifdef USE_SSL_SOCKET
/**
* The flags that control the test SSL client behavior.
*
* These flags augment the environment variables prefixed by
* 'LIBPROCESS_SSL_' that are introduced by @see
* process::network::openssl::Flags.
*/
class Flags : public virtual flags::FlagsBase
{
public:
Flags()
{
add(&Flags::use_ssl,
"use_ssl",
"Whether to try and connect using an SSL based socket. This is "
"separate from whether LIBPROCESS_SSL_ENABLED is set. We use "
"this for testing failure cases.",
true);
add(&Flags::data,
"data",
"The message to send as the client.",
"Hello World");
add(&Flags::server,
"server",
"IP address of server",
"127.0.0.1");
add(&Flags::server_hostname,
"server_hostname",
"Hostname of server");
add(&Flags::port, "port", "Port of server", 5050);
}
bool use_ssl;
string data;
string server;
Option<string> server_hostname;
uint16_t port;
};
class SSLClientTest : public ::testing::Test
{
public:
static Flags flags;
};
Flags SSLClientTest::flags;
int main(int argc, char** argv)
{
// Load all the client flags.
Try<flags::Warnings> load = SSLClientTest::flags.load("", argc, argv);
if (load.isError()) {
EXIT(EXIT_FAILURE) << "Failed to load flags: " << load.error();
}
if (SSLClientTest::flags.help) {
cout << SSLClientTest::flags.usage() << endl;
return EXIT_SUCCESS;
}
// Log any flag warnings.
foreach (const flags::Warning& warning, load->warnings) {
cout << warning.message << endl;
}
process::initialize();
openssl::initialize();
// Initialize Google Mock/Test.
testing::InitGoogleMock(&argc, argv);
// Add the libprocess test event listeners.
::testing::TestEventListeners& listeners =
::testing::UnitTest::GetInstance()->listeners();
listeners.Append(process::ClockTestEventListener::instance());
listeners.Append(process::FilterTestEventListener::instance());
return RUN_ALL_TESTS();
}
TEST_F(SSLClientTest, client)
{
// Create the socket based on the 'use_ssl' flag. We use this to
// test whether a regular socket could connect to an SSL server
// socket.
const Try<Socket> create = Socket::create(
flags.use_ssl ? SocketImpl::Kind::SSL : SocketImpl::Kind::POLL);
ASSERT_SOME(create);
Socket socket = create.get();
Try<net::IP> ip = net::IP::parse(flags.server, AF_INET);
EXPECT_SOME(ip);
// Connect to the server.
Address address(ip.get(), flags.port);
Future<Nothing> connect = [&]() {
switch(socket.kind()) {
case SocketImpl::Kind::POLL:
return socket.connect(address);
case SocketImpl::Kind::SSL:
return socket.connect(
address,
openssl::create_tls_client_config(flags.server_hostname));
}
UNREACHABLE();
}();
// Verify that the client views the connection as established.
AWAIT_EXPECT_READY(connect);
// Send 'data' from the client to the server.
AWAIT_EXPECT_READY(socket.send(flags.data));
// Verify the client received the message back from the server.
AWAIT_EXPECT_EQ(flags.data, socket.recv());
}
#endif // USE_SSL_SOCKET