Skip to content
Permalink
Browse files

Add tests for S3Simulator and S3Client

  • Loading branch information
qris committed Nov 18, 2016
1 parent 1b4d294 commit 50f57e54cfff225933248152e242f4885a28fc9a
@@ -18,7 +18,7 @@
#include <sys/types.h>

#ifdef HAVE_DIRENT_H
# include <dirent.h>
# include <dirent.h> // for opendir(), struct DIR
#endif

#ifdef HAVE_UNISTD_H
@@ -87,6 +87,8 @@ bool setUp(const char* function_name)
}
}

// We need to do something more complex than "rm -rf testfiles" to clean up the mess and
// prepare for the next test, in a way that works on Windows (without rm -rf) as well.
DIR* pDir = opendir("testfiles");
if(!pDir)
{
@@ -104,16 +106,16 @@ bool setUp(const char* function_name)
StartsWith("notifyran", filename) ||
StartsWith("notifyscript.tag", filename) ||
StartsWith("restore", filename) ||
filename == "store" ||
filename == "bbackupd-cache" ||
filename == "bbackupd-data" ||
filename == "store" ||
filename == "syncallowscript.control" ||
StartsWith("syncallowscript.notifyran.", filename) ||
filename == "test2.downloaded" ||
EndsWith("testfile", filename))
{
std::string filepath = std::string("testfiles"
DIRECTORY_SEPARATOR) + filename;
std::string filepath = std::string("testfiles" DIRECTORY_SEPARATOR) +
filename;

int filetype = ObjectExists(filepath);
if(filetype == ObjectExists_File)
@@ -126,7 +128,9 @@ bool setUp(const char* function_name)
}
else if(filetype == ObjectExists_Dir)
{
#ifdef WIN32
#ifdef _MSC_VER
// More complex command invocation required to properly encode
// arguments when non-ASCII characters are involved:
std::string cmd = "cmd /c rd /s /q " + filepath;
WCHAR* wide_cmd = ConvertUtf8ToWideString(cmd.c_str());
if(wide_cmd == NULL)
@@ -188,11 +192,11 @@ bool setUp(const char* function_name)

CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
#else // !WIN32
#else // !_MSC_VER
// Deleting directories is so much easier on Unix!
std::string cmd = "rm -rf '" + filepath + "'";
TEST_THAT_THROWONFAIL(system(cmd.c_str()) == 0);
#endif // WIN32
TEST_EQUAL_LINE(0, system(cmd.c_str()), "system() failed: " << cmd);
#endif
}
else
{
@@ -213,6 +217,7 @@ bool setUp(const char* function_name)
TEST_THAT_THROWONFAIL(mkdir("testfiles/bbackupd-cache", 0755) == 0);
TEST_THAT_THROWONFAIL(mkdir("testfiles/store", 0755) == 0);
TEST_THAT_THROWONFAIL(mkdir("testfiles/store/subdir", 0755) == 0);
TEST_THAT_THROWONFAIL(mkdir("testfiles/store/subdir/dirs", 0755) == 0);

return true;
}
@@ -0,0 +1,44 @@
// --------------------------------------------------------------------------
//
// File
// Name: HTTPTest.cpp
// Purpose: Amazon S3 simulator start/stop functions
// Created: 14/11/2016
//
// --------------------------------------------------------------------------

#include "Box.h"

#include "ServerControl.h"
#include "Utils.h"

static int s3simulator_pid;

bool StartSimulator()
{
s3simulator_pid = StartDaemon(s3simulator_pid,
"../../bin/s3simulator/s3simulator " + bbstored_args +
" testfiles/s3simulator.conf", "testfiles/s3simulator.pid");
return s3simulator_pid != 0;
}

bool StopSimulator()
{
bool result = StopDaemon(s3simulator_pid, "testfiles/s3simulator.pid",
"s3simulator.memleaks", true);
s3simulator_pid = 0;
return result;
}

bool kill_simulator_if_running()
{
bool success = true;

if(FileExists("testfiles/s3simulator.pid"))
{
TEST_THAT_OR(KillServer("testfiles/s3simulator.pid", true), success = false);
}

return success;
}

@@ -0,0 +1,18 @@
// --------------------------------------------------------------------------
//
// File
// Name: HTTPTest.h
// Purpose: Amazon S3 simulator start/stop functions
// Created: 14/11/2016
//
// --------------------------------------------------------------------------

#ifndef HTTPTEST__H
#define HTTPTEST__H

bool StartSimulator();
bool StopSimulator();
bool kill_simulator_if_running();

#endif // HTTPTEST__H

@@ -0,0 +1 @@
omgpuppies!
@@ -1,6 +1,6 @@
AccessKey = 0PN5J17HBGZHT7JJ3X82
SecretKey = uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o
StoreDirectory = testfiles
StoreDirectory = testfiles/store
AddressPrefix = http://localhost:1080

Server
@@ -25,6 +25,7 @@
#include "HTTPRequest.h"
#include "HTTPResponse.h"
#include "HTTPServer.h"
#include "HTTPTest.h"
#include "IOStreamGetLine.h"
#include "S3Client.h"
#include "S3Simulator.h"
@@ -41,11 +42,12 @@
class TestWebServer : public HTTPServer
{
public:
TestWebServer();
~TestWebServer();
TestWebServer()
: HTTPServer(LONG_TIMEOUT)
{ }
~TestWebServer() { }

virtual void Handle(HTTPRequest &rRequest, HTTPResponse &rResponse);

};

// Build a nice HTML response, so this can also be tested neatly in a browser
@@ -127,8 +129,32 @@ void TestWebServer::Handle(HTTPRequest &rRequest, HTTPResponse &rResponse)
rResponse.Write(DEFAULT_RESPONSE_2, sizeof(DEFAULT_RESPONSE_2) - 1);
}

TestWebServer::TestWebServer() {}
TestWebServer::~TestWebServer() {}
bool exercise_s3client(S3Client& client)
{
int num_failures_initial = num_failures;

HTTPResponse response = client.GetObject("/photos/puppy.jpg");
TEST_EQUAL(200, response.GetResponseCode());
std::string response_data((const char *)response.GetBuffer(),
response.GetSize());
TEST_EQUAL("omgpuppies!\n", response_data);
TEST_THAT(!response.IsKeepAlive());

// make sure that assigning to HTTPResponse does clear stream
response = client.GetObject("/photos/puppy.jpg");
TEST_EQUAL(200, response.GetResponseCode());
response_data = std::string((const char *)response.GetBuffer(),
response.GetSize());
TEST_EQUAL("omgpuppies!\n", response_data);
TEST_THAT(!response.IsKeepAlive());

response = client.GetObject("/nonexist");
TEST_EQUAL(404, response.GetResponseCode());
TEST_THAT(!response.IsKeepAlive());

// Test is successful if the number of failures has not increased.
return (num_failures == num_failures_initial);
}

// http://docs.aws.amazon.com/AmazonSimpleDB/latest/DeveloperGuide/HMACAuth.html
std::string calculate_s3_signature(const HTTPRequest& request,
@@ -423,6 +449,14 @@ bool test_httpserver()
TEST_THAT(StopDaemon(pid, "testfiles/httpserver.pid",
"generic-httpserver.memleaks", true));

// Copy testfiles/puppy.jpg to testfiles/store/photos/puppy.jpg
{
TEST_THAT(::mkdir("testfiles/store/photos", 0755) == 0);
FileStream in("testfiles/puppy.jpg", O_RDONLY);
FileStream out("testfiles/store/photos/puppy.jpg", O_CREAT | O_WRONLY);
in.CopyStreamTo(out);
}

// This is the example from the Amazon S3 Developers Guide, page 31.
// Correct, official signature should succeed, with lower-case headers.
{
@@ -511,7 +545,7 @@ bool test_httpserver()
response = client.GetObject("/newfile");
TEST_EQUAL(200, response.GetResponseCode());
TEST_THAT(fs.CompareWith(response));
TEST_EQUAL(0, ::unlink("testfiles/newfile"));
TEST_EQUAL(0, ::unlink("testfiles/store/newfile"));
}

{
@@ -549,9 +583,25 @@ bool test_httpserver()
TEST_EQUAL(0, response.GetSize());

FileStream f1("testfiles/testrequests.pl");
FileStream f2("testfiles/newfile");
FileStream f2("testfiles/store/newfile");
TEST_THAT(f1.CompareWith(f2));
TEST_EQUAL(0, ::unlink("testfiles/newfile"));
TEST_EQUAL(0, ::unlink("testfiles/store/newfile"));
}

// Copy testfiles/dsfdsfs98.fd to testfiles/store/dsfdsfs98.fd
{
FileStream in("testfiles/dsfdsfs98.fd", O_RDONLY);
FileStream out("testfiles/store/dsfdsfs98.fd", O_CREAT | O_WRONLY);
in.CopyStreamTo(out);
}

// S3Client tests with S3Simulator in-process server for debugging
{
S3Simulator simulator;
simulator.Configure("testfiles/s3simulator.conf");
S3Client client(&simulator, "johnsmith.s3.amazonaws.com",
EXAMPLE_S3_ACCESS_KEY, EXAMPLE_S3_SECRET_KEY);
TEST_THAT(exercise_s3client(client));
}

// Start the S3Simulator server
@@ -571,6 +621,7 @@ bool test_httpserver()
TEST_THAT(send_and_receive(request, response));
}

// Test that requests for nonexistent files correctly return a 404 error
{
HTTPRequest request(HTTPRequest::Method_GET, "/nonexist");
request.SetHostName("quotes.s3.amazonaws.com");
@@ -592,7 +643,7 @@ bool test_httpserver()
// Make file inaccessible, should cause server to return a 403 error,
// unless of course the test is run as root :)
{
TEST_THAT(chmod("testfiles/dsfdsfs98.fd", 0) == 0);
TEST_THAT(chmod("testfiles/store/dsfdsfs98.fd", 0) == 0);
HTTPRequest request(HTTPRequest::Method_GET, "/dsfdsfs98.fd");
request.SetHostName("quotes.s3.amazonaws.com");
request.AddHeader("Date", "Wed, 01 Mar 2006 12:00:00 GMT");
@@ -602,7 +653,7 @@ bool test_httpserver()

HTTPResponse response;
TEST_THAT(send_and_receive(request, response, 403));
TEST_THAT(chmod("testfiles/dsfdsfs98.fd", 0755) == 0);
TEST_THAT(chmod("testfiles/store/dsfdsfs98.fd", 0755) == 0);
}
#endif

@@ -657,15 +708,33 @@ bool test_httpserver()
TEST_THAT(!response.IsKeepAlive());

FileStream f1("testfiles/dsfdsfs98.fd");
FileStream f2("testfiles/newfile");
FileStream f2("testfiles/store/newfile");
TEST_THAT(f1.CompareWith(f2));
TEST_THAT(::unlink("testfiles/newfile") == 0);
TEST_THAT(::unlink("testfiles/store/newfile") == 0);
}

// S3Client tests with S3Simulator daemon for realism
{
S3Client client("localhost", 1080, EXAMPLE_S3_ACCESS_KEY,
EXAMPLE_S3_SECRET_KEY);
TEST_THAT(exercise_s3client(client));
}

// Kill it
TEST_THAT(StopDaemon(pid, "testfiles/s3simulator.pid",
"s3simulator.memleaks", true));

TEST_THAT(StartSimulator());

// S3Client tests with s3simulator executable for even more realism
{
S3Client client("localhost", 1080, EXAMPLE_S3_ACCESS_KEY,
EXAMPLE_S3_SECRET_KEY);
TEST_THAT(exercise_s3client(client));
}

TEST_THAT(StopSimulator());

TEARDOWN();
}

0 comments on commit 50f57e5

Please sign in to comment.
You can’t perform that action at this time.