-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}.