-module(httptest).
-export([main/1]).
main([Server]) ->
application:start(inets),
% create the database
DB = atom_to_list(Server) ++ "test_suite_db/",
http(delete, DB),
{201, _, _} = http(put, DB, [], <<>>),
% run the tests
io:format("Running Tests"),
content_encoding_tests(DB),
content_negotiation_tests(DB),
conditional_processing_tests(DB),
io:format("~n~nTests Passed!~n"),
init:stop().
%----------------------------------------------------------------------
% test gzip and deflate
content_encoding_tests(DB) ->
ID = DB ++ "test_doc",
Doc = "{\"hello\": \"world\"}",
% create a doc
{201, _, _} = http(put, ID, [], Doc),
% baseline
{200, Hdrs_u, Doc_u} = http(get, ID),
[] = [ Value || {"content-encoding",Value} <- Hdrs_u],
% gzip
{200, Hdrs_gz, Doc_gz} = http(get, ID, [{"accept-encoding", "gzip"}]),
["gzip"] = [ Value || {"content-encoding",Value} <- Hdrs_gz],
Doc_u = binary_to_list(zlib:gunzip(list_to_binary(Doc_gz))),
% deflate
{200, Hdrs_d, Doc_d} = http(get, ID, [{"accept-encoding", "deflate"}]),
["deflate"] = [ Value || {"content-encoding",Value} <- Hdrs_d],
Z = zlib:open(),
zlib:inflateInit(Z),
[Doc_du] = zlib:inflate(Z, list_to_binary(Doc_d)),
Doc_u = binary_to_list(Doc_du),
zlib:inflateEnd(Z),
zlib:close(Z),
% delete the doc
{202, _, _} = http(delete, ID),
% test passed
io:format(".").
%----------------------------------------------------------------------
% Return application/json content type, if requested
content_negotiation_tests(DB) ->
ID = DB ++ "test_doc",
Doc = "{\"hello\": \"world\"}",
% create a doc
{201, _, _} = http(put, ID, [], Doc),
% baseline
{200, Hdrs_plain, _} = http(get, ID, [{"accept", "text/html"}]),
[["text/plain"| _Rest]] =
[string:tokens(Value,";") || {"content-type",Value} <- Hdrs_plain],
{200, Hdrs_json, _} = http(get, ID, [{"accept", "application/json"}]),
[["application/json"| _Rest]] =
[string:tokens(Value,";") || {"content-type",Value} <- Hdrs_json],
% delete the doc
{202, _, _} = http(delete, ID),
% test passed
io:format(".").
%----------------------------------------------------------------------
% test Etag, Last-Modified, and If-* headers
conditional_processing_tests(DB) ->
ID = DB ++ "test_doc",
Doc = "{\"hello\": \"world\"}",
% create a doc
{201, Put_headers, _} = http(put, ID, [], Doc),
% extract the ETag and Last-Modified header values
[ETag1] = [ Value || {"etag",Value} <- Put_headers],
[Mod1] = [ Value || {"last-modified",Value} <- Put_headers],
% get the doc
{200, Get_headers, Doc2} = http(get, ID),
% verify the headers match
[ETag1] = [ Value || {"etag",Value} <- Get_headers],
[Mod1] = [ Value || {"last-modified",Value} <- Get_headers],
% 'head' the doc
{200, Head_headers, _} = http(head, ID),
% verify the headers match
[ETag1] = [ Value || {"etag",Value} <- Head_headers],
[Mod1] = [ Value || {"last-modified",Value} <- Head_headers],
% replace a doc
Check = [{"if-match", ETag1}, {"if-unmodified-since", Mod1}],
{201, Put2_headers, _} = http(put, ID, Check, Doc2),
% extract the new ETag and Last-Modified header values
[ETag2] = [ Value || {"etag",Value} <- Put2_headers],
[Mod2] = [ Value || {"last-modified",Value} <- Put2_headers],
% fail to replace a doc
{409, _, _} = http(put, ID, Check, Doc), % should be 412
% verify get w/Etag
{200, _, _} = http(get, ID, [{"if-none-match", ETag1}]),
{304, _, _} = http(get, ID, [{"if-none-match", ETag2}]),
% verify get w/Last Modified
if Mod1 /= Mod2 ->
{200, _, _} = http(get, ID, [{"if-modified-since", Mod1}]);
true ->
{304, _, _} = http(get, ID, [{"if-modified-since", Mod2}])
end,
% fail to delete a doc
{412, _, _} = http(delete, ID, Check),
% now do it for real
Check2 = [{"if-match", ETag2}, {"if-unmodified-since", Mod2}],
{202, _, _} = http(delete, ID, Check2),
% test passed
io:format(".").
%----------------------------------------------------------------------
% convenience functions: shortcuts to
http(Method, URI) ->
{ok, {{_HttpVersion ,Code, _Reason}, Response_Headers, Body}} =
http:request(Method, {URI, []}, [], []),
{Code, Response_Headers, Body}.
http(Method, URI, Request_Headers) ->
{ok, {{_HttpVersion ,Code, _Reason}, Response_Headers, Body}} =
http:request(Method, {URI, Request_Headers}, [], []),
{Code, Response_Headers, Body}.
http(Method, URI, Request_Headers, Data) ->
JSON = "application/json; charset=utf-8",
{ok, {{_HttpVersion ,Code, _Reason}, Response_Headers, Body}} =
http:request(Method, {URI, Request_Headers, JSON, Data}, [], []),
{Code, Response_Headers, Body}.