diff options
author | Alexander Shorin <kxepal@apache.org> | 2014-06-03 01:51:46 +0400 |
---|---|---|
committer | Alexander Shorin <kxepal@apache.org> | 2015-12-02 03:49:05 +0300 |
commit | 3a91b3a9250abb474ac7c690225bda233c83659e (patch) | |
tree | 6020de03ca7d2257253fac306adffc1cd095f05a | |
parent | dd01551b9d2b042f7beac525fc32a499e4194bcf (diff) | |
download | couchdb-3a91b3a9250abb474ac7c690225bda233c83659e.tar.gz |
Port 140-attachments-comp.t etap test suite to eunit
- Merge into couchdb_attachments_tests suite;
- Add PUT requests to test_request util;
- Remove dependency from files outside fixtures directory;
- Group test cases to reduce amount of duplicate code;
- Fix hidden issue with gzip encoding: for encoding_length stub info
check using zlib:gzip on 2KiB+ files leads to mismatch by 2-4 bytes
and this difference grows with file size. Using gzip fun code from
couch_stream solves the issue.
-rw-r--r-- | license.skip | 1 | ||||
-rw-r--r-- | test/couchdb/Makefile.am | 3 | ||||
-rw-r--r-- | test/couchdb/couchdb_attachments_tests.erl | 380 | ||||
-rw-r--r-- | test/couchdb/fixtures/logo.png | bin | 0 -> 3010 bytes | |||
-rw-r--r-- | test/couchdb/test_request.erl | 9 | ||||
-rwxr-xr-x | test/etap/140-attachment-comp.t | 728 | ||||
-rw-r--r-- | test/etap/Makefile.am | 1 |
7 files changed, 388 insertions, 734 deletions
diff --git a/license.skip b/license.skip index aab5fc256..3050026ce 100644 --- a/license.skip +++ b/license.skip @@ -166,6 +166,7 @@ ^test/Makefile.in ^test/couchdb/Makefile ^test/couchdb/Makefile.in +^test/couchdb/fixtures/logo.png ^test/etap/.*.beam ^test/etap/.*.o ^test/etap/.deps/.* diff --git a/test/couchdb/Makefile.am b/test/couchdb/Makefile.am index 540583b5f..9a4dda5bb 100644 --- a/test/couchdb/Makefile.am +++ b/test/couchdb/Makefile.am @@ -48,7 +48,8 @@ fixture_files = \ fixtures/couch_config_tests_1.ini \ fixtures/couch_config_tests_2.ini \ fixtures/couch_stats_aggregates.cfg \ - fixtures/couch_stats_aggregates.ini + fixtures/couch_stats_aggregates.ini \ + fixtures/logo.png EXTRA_DIST = \ run.in \ diff --git a/test/couchdb/couchdb_attachments_tests.erl b/test/couchdb/couchdb_attachments_tests.erl index aef187324..cf597855b 100644 --- a/test/couchdb/couchdb_attachments_tests.erl +++ b/test/couchdb/couchdb_attachments_tests.erl @@ -15,13 +15,23 @@ -include("couch_eunit.hrl"). -include_lib("couchdb/couch_db.hrl"). +-define(COMPRESSION_LEVEL, 8). +-define(ATT_BIN_NAME, <<"logo.png">>). +-define(ATT_TXT_NAME, <<"file.erl">>). +-define(FIXTURE_PNG, filename:join([?FIXTURESDIR, "logo.png"])). +-define(FIXTURE_TXT, ?FILE). -define(TIMEOUT, 1000). +-define(TIMEOUT_EUNIT, 10). -define(TIMEWAIT, 100). -define(i2l(I), integer_to_list(I)). start() -> {ok, Pid} = couch_server_sup:start_link(?CONFIG_CHAIN), + % ensure in default compression settings for attachments_compression_tests + couch_config:set("attachments", "compression_level", + ?i2l(?COMPRESSION_LEVEL), false), + couch_config:set("attachments", "compressible_types", "text/*", false), Pid. stop(Pid) -> @@ -43,7 +53,35 @@ setup() -> Host = Addr ++ ":" ++ ?i2l(Port), {Host, ?b2l(DbName)}. +setup({binary, standalone}) -> + {Host, DbName} = setup(), + setup_att(fun create_standalone_png_att/2, Host, DbName, ?FIXTURE_PNG); +setup({text, standalone}) -> + {Host, DbName} = setup(), + setup_att(fun create_standalone_text_att/2, Host, DbName, ?FIXTURE_TXT); +setup({binary, inline}) -> + {Host, DbName} = setup(), + setup_att(fun create_inline_png_att/2, Host, DbName, ?FIXTURE_PNG); +setup({text, inline}) -> + {Host, DbName} = setup(), + setup_att(fun create_inline_text_att/2, Host, DbName, ?FIXTURE_TXT); +setup(compressed) -> + {Host, DbName} = setup(), + setup_att(fun create_already_compressed_att/2, Host, DbName, ?FIXTURE_TXT). +setup_att(Fun, Host, DbName, File) -> + HttpHost = "http://" ++ Host, + AttUrl = Fun(HttpHost, DbName), + {ok, Data} = file:read_file(File), + DocUrl = string:join([HttpHost, DbName, "doc"], "/"), + Helpers = {DbName, DocUrl, AttUrl}, + {Data, Helpers}. + +teardown(_, {_, {DbName, _, _}}) -> + teardown(DbName). + teardown({_, DbName}) -> + teardown(DbName); +teardown(DbName) -> ok = couch_server:delete(?l2b(DbName), []), ok. @@ -55,7 +93,8 @@ attachments_test_() -> setup, fun start/0, fun stop/1, [ - attachments_md5_tests() + attachments_md5_tests(), + attachments_compression_tests() ] } }. @@ -79,6 +118,67 @@ attachments_md5_tests() -> } }. +attachments_compression_tests() -> + Funs = [ + fun should_get_att_without_accept_gzip_encoding/2, + fun should_get_att_with_accept_gzip_encoding/2, + fun should_get_att_with_accept_deflate_encoding/2, + fun should_return_406_response_on_unsupported_encoding/2, + fun should_get_doc_with_att_data/2, + fun should_get_doc_with_att_data_stub/2 + ], + { + "Attachments compression tests", + [ + { + "Created via Attachments API", + created_attachments_compression_tests(standalone, Funs) + }, + { + "Created inline via Document API", + created_attachments_compression_tests(inline, Funs) + }, + { + "Created already been compressed via Attachments API", + { + foreachx, + fun setup/1, fun teardown/2, + [{compressed, Fun} || Fun <- Funs] + } + }, + { + foreach, + fun setup/0, fun teardown/1, + [ + fun should_not_create_compressed_att_with_deflate_encoding/1, + fun should_not_create_compressed_att_with_compress_encoding/1, + fun should_create_compressible_att_with_ctype_params/1 + ] + } + ] + }. + +created_attachments_compression_tests(Mod, Funs) -> + [ + { + "Compressiable attachments", + { + foreachx, + fun setup/1, fun teardown/2, + [{{text, Mod}, Fun} || Fun <- Funs] + } + }, + { + "Uncompressiable attachments", + { + foreachx, + fun setup/1, fun teardown/2, + [{{binary, Mod}, Fun} || Fun <- Funs] + } + } + ]. + + should_upload_attachment_without_md5({Host, DbName}) -> ?_test(begin @@ -212,10 +312,218 @@ should_reject_chunked_attachment_with_invalid_md5_trailer({Host, DbName}) -> ], {ok, Code, Json} = request("PUT", AttUrl, Headers, Body), ?assertEqual(400, Code), - ?assertEqual(<<"content_md5_mismatch">>, - get_json(Json, [<<"error">>])) + ?assertEqual(<<"content_md5_mismatch">>, get_json(Json, [<<"error">>])) + end). + +should_get_att_without_accept_gzip_encoding(_, {Data, {_, _, AttUrl}}) -> + ?_test(begin + {ok, Code, Headers, Body} = test_request:get(AttUrl), + ?assertEqual(200, Code), + ?assertNot(lists:member({"Content-Encoding", "gzip"}, Headers)), + ?assertEqual(Data, iolist_to_binary(Body)) + end). + +should_get_att_with_accept_gzip_encoding(compressed, {Data, {_, _, AttUrl}}) -> + ?_test(begin + {ok, Code, Headers, Body} = test_request:get( + AttUrl, [{"Accept-Encoding", "gzip"}]), + ?assertEqual(200, Code), + ?assert(lists:member({"Content-Encoding", "gzip"}, Headers)), + ?assertEqual(Data, zlib:gunzip(iolist_to_binary(Body))) + end); +should_get_att_with_accept_gzip_encoding({text, _}, {Data, {_, _, AttUrl}}) -> + ?_test(begin + {ok, Code, Headers, Body} = test_request:get( + AttUrl, [{"Accept-Encoding", "gzip"}]), + ?assertEqual(200, Code), + ?assert(lists:member({"Content-Encoding", "gzip"}, Headers)), + ?assertEqual(Data, zlib:gunzip(iolist_to_binary(Body))) + end); +should_get_att_with_accept_gzip_encoding({binary, _}, {Data, {_, _, AttUrl}}) -> + ?_test(begin + {ok, Code, Headers, Body} = test_request:get( + AttUrl, [{"Accept-Encoding", "gzip"}]), + ?assertEqual(200, Code), + ?assertEqual(undefined, + couch_util:get_value("Content-Encoding", Headers)), + ?assertEqual(Data, iolist_to_binary(Body)) + end). + +should_get_att_with_accept_deflate_encoding(_, {Data, {_, _, AttUrl}}) -> + ?_test(begin + {ok, Code, Headers, Body} = test_request:get( + AttUrl, [{"Accept-Encoding", "deflate"}]), + ?assertEqual(200, Code), + ?assertEqual(undefined, + couch_util:get_value("Content-Encoding", Headers)), + ?assertEqual(Data, iolist_to_binary(Body)) + end). + +should_return_406_response_on_unsupported_encoding(_, {_, {_, _, AttUrl}}) -> + ?_assertEqual(406, + begin + {ok, Code, _, _} = test_request:get( + AttUrl, [{"Accept-Encoding", "deflate, *;q=0"}]), + Code + end). + +should_get_doc_with_att_data(compressed, {Data, {_, DocUrl, _}}) -> + ?_test(begin + Url = DocUrl ++ "?attachments=true", + {ok, Code, _, Body} = test_request:get( + Url, [{"Accept", "application/json"}]), + ?assertEqual(200, Code), + Json = ejson:decode(Body), + AttJson = couch_util:get_nested_json_value( + Json, [<<"_attachments">>, ?ATT_TXT_NAME]), + AttData = couch_util:get_nested_json_value( + AttJson, [<<"data">>]), + ?assertEqual( + <<"text/plain">>, + couch_util:get_nested_json_value(AttJson,[<<"content_type">>])), + ?assertEqual(Data, base64:decode(AttData)) + end); +should_get_doc_with_att_data({text, _}, {Data, {_, DocUrl, _}}) -> + ?_test(begin + Url = DocUrl ++ "?attachments=true", + {ok, Code, _, Body} = test_request:get( + Url, [{"Accept", "application/json"}]), + ?assertEqual(200, Code), + Json = ejson:decode(Body), + AttJson = couch_util:get_nested_json_value( + Json, [<<"_attachments">>, ?ATT_TXT_NAME]), + AttData = couch_util:get_nested_json_value( + AttJson, [<<"data">>]), + ?assertEqual( + <<"text/plain">>, + couch_util:get_nested_json_value(AttJson,[<<"content_type">>])), + ?assertEqual(Data, base64:decode(AttData)) + end); +should_get_doc_with_att_data({binary, _}, {Data, {_, DocUrl, _}}) -> + ?_test(begin + Url = DocUrl ++ "?attachments=true", + {ok, Code, _, Body} = test_request:get( + Url, [{"Accept", "application/json"}]), + ?assertEqual(200, Code), + Json = ejson:decode(Body), + AttJson = couch_util:get_nested_json_value( + Json, [<<"_attachments">>, ?ATT_BIN_NAME]), + AttData = couch_util:get_nested_json_value( + AttJson, [<<"data">>]), + ?assertEqual( + <<"image/png">>, + couch_util:get_nested_json_value(AttJson,[<<"content_type">>])), + ?assertEqual(Data, base64:decode(AttData)) + end). + +should_get_doc_with_att_data_stub(compressed, {Data, {_, DocUrl, _}}) -> + ?_test(begin + Url = DocUrl ++ "?att_encoding_info=true", + {ok, Code, _, Body} = test_request:get( + Url, [{"Accept", "application/json"}]), + ?assertEqual(200, Code), + Json = ejson:decode(Body), + {AttJson} = couch_util:get_nested_json_value( + Json, [<<"_attachments">>, ?ATT_TXT_NAME]), + ?assertEqual(<<"gzip">>, + couch_util:get_value(<<"encoding">>, AttJson)), + AttLength = couch_util:get_value(<<"length">>, AttJson), + EncLength = couch_util:get_value(<<"encoded_length">>, AttJson), + ?assertEqual(AttLength, EncLength), + ?assertEqual(iolist_size(zlib:gzip(Data)), AttLength) + end); +should_get_doc_with_att_data_stub({text, _}, {Data, {_, DocUrl, _}}) -> + ?_test(begin + Url = DocUrl ++ "?att_encoding_info=true", + {ok, Code, _, Body} = test_request:get( + Url, [{"Accept", "application/json"}]), + ?assertEqual(200, Code), + Json = ejson:decode(Body), + {AttJson} = couch_util:get_nested_json_value( + Json, [<<"_attachments">>, ?ATT_TXT_NAME]), + ?assertEqual(<<"gzip">>, + couch_util:get_value(<<"encoding">>, AttJson)), + AttEncLength = iolist_size(gzip(Data)), + ?assertEqual(AttEncLength, + couch_util:get_value(<<"encoded_length">>, AttJson)), + ?assertEqual(byte_size(Data), + couch_util:get_value(<<"length">>, AttJson)) + end); +should_get_doc_with_att_data_stub({binary, _}, {Data, {_, DocUrl, _}}) -> + ?_test(begin + Url = DocUrl ++ "?att_encoding_info=true", + {ok, Code, _, Body} = test_request:get( + Url, [{"Accept", "application/json"}]), + ?assertEqual(200, Code), + Json = ejson:decode(Body), + {AttJson} = couch_util:get_nested_json_value( + Json, [<<"_attachments">>, ?ATT_BIN_NAME]), + ?assertEqual(undefined, + couch_util:get_value(<<"encoding">>, AttJson)), + ?assertEqual(undefined, + couch_util:get_value(<<"encoded_length">>, AttJson)), + ?assertEqual(byte_size(Data), + couch_util:get_value(<<"length">>, AttJson)) end). +should_not_create_compressed_att_with_deflate_encoding({Host, DbName}) -> + ?_assertEqual(415, + begin + HttpHost = "http://" ++ Host, + AttUrl = string:join([HttpHost, DbName, ?docid(), "file.txt"], "/"), + {ok, Data} = file:read_file(?FIXTURE_TXT), + Body = zlib:compress(Data), + Headers = [ + {"Content-Encoding", "deflate"}, + {"Content-Type", "text/plain"} + ], + {ok, Code, _, _} = test_request:put(AttUrl, Headers, Body), + Code + end). + +should_not_create_compressed_att_with_compress_encoding({Host, DbName}) -> + % Note: As of OTP R13B04, it seems there's no LZW compression + % (i.e. UNIX compress utility implementation) lib in OTP. + % However there's a simple working Erlang implementation at: + % http://scienceblogs.com/goodmath/2008/01/simple_lempelziv_compression_i.php + ?_assertEqual(415, + begin + HttpHost = "http://" ++ Host, + AttUrl = string:join([HttpHost, DbName, ?docid(), "file.txt"], "/"), + {ok, Data} = file:read_file(?FIXTURE_TXT), + Headers = [ + {"Content-Encoding", "compress"}, + {"Content-Type", "text/plain"} + ], + {ok, Code, _, _} = test_request:put(AttUrl, Headers, Data), + Code + end). + +should_create_compressible_att_with_ctype_params({Host, DbName}) -> + {timeout, ?TIMEOUT_EUNIT, ?_test(begin + HttpHost = "http://" ++ Host, + DocUrl = string:join([HttpHost, DbName, ?docid()], "/"), + AttUrl = string:join([DocUrl, ?b2l(?ATT_TXT_NAME)], "/"), + {ok, Data} = file:read_file(?FIXTURE_TXT), + Headers = [{"Content-Type", "text/plain; charset=UTF-8"}], + {ok, Code0, _, _} = test_request:put(AttUrl, Headers, Data), + ?assertEqual(201, Code0), + + {ok, Code1, _, Body} = test_request:get( + DocUrl ++ "?att_encoding_info=true"), + ?assertEqual(200, Code1), + Json = ejson:decode(Body), + {AttJson} = couch_util:get_nested_json_value( + Json, [<<"_attachments">>, ?ATT_TXT_NAME]), + ?assertEqual(<<"gzip">>, + couch_util:get_value(<<"encoding">>, AttJson)), + AttEncLength = iolist_size(gzip(Data)), + ?assertEqual(AttEncLength, + couch_util:get_value(<<"encoded_length">>, AttJson)), + ?assertEqual(byte_size(Data), + couch_util:get_value(<<"length">>, AttJson)) + end)}. + get_json(Json, Path) -> couch_util:get_nested_json_value(Json, Path). @@ -262,3 +570,69 @@ request(Method, Url, Headers, Body) -> erlang:decode_packet(http, Header, []), Json = ejson:decode(Body1), {ok, Code, Json}. + +create_standalone_text_att(Host, DbName) -> + {ok, Data} = file:read_file(?FIXTURE_TXT), + Url = string:join([Host, DbName, "doc", ?b2l(?ATT_TXT_NAME)], "/"), + {ok, Code, _Headers, _Body} = test_request:put( + Url, [{"Content-Type", "text/plain"}], Data), + ?assertEqual(201, Code), + Url. + +create_standalone_png_att(Host, DbName) -> + {ok, Data} = file:read_file(?FIXTURE_PNG), + Url = string:join([Host, DbName, "doc", ?b2l(?ATT_BIN_NAME)], "/"), + {ok, Code, _Headers, _Body} = test_request:put( + Url, [{"Content-Type", "image/png"}], Data), + ?assertEqual(201, Code), + Url. + +create_inline_text_att(Host, DbName) -> + {ok, Data} = file:read_file(?FIXTURE_TXT), + Url = string:join([Host, DbName, "doc"], "/"), + Doc = {[ + {<<"_attachments">>, {[ + {?ATT_TXT_NAME, {[ + {<<"content_type">>, <<"text/plain">>}, + {<<"data">>, base64:encode(Data)} + ]} + }]}} + ]}, + {ok, Code, _Headers, _Body} = test_request:put( + Url, [{"Content-Type", "application/json"}], ejson:encode(Doc)), + ?assertEqual(201, Code), + string:join([Url, ?b2l(?ATT_TXT_NAME)], "/"). + +create_inline_png_att(Host, DbName) -> + {ok, Data} = file:read_file(?FIXTURE_PNG), + Url = string:join([Host, DbName, "doc"], "/"), + Doc = {[ + {<<"_attachments">>, {[ + {?ATT_BIN_NAME, {[ + {<<"content_type">>, <<"image/png">>}, + {<<"data">>, base64:encode(Data)} + ]} + }]}} + ]}, + {ok, Code, _Headers, _Body} = test_request:put( + Url, [{"Content-Type", "application/json"}], ejson:encode(Doc)), + ?assertEqual(201, Code), + string:join([Url, ?b2l(?ATT_BIN_NAME)], "/"). + +create_already_compressed_att(Host, DbName) -> + {ok, Data} = file:read_file(?FIXTURE_TXT), + Url = string:join([Host, DbName, "doc", ?b2l(?ATT_TXT_NAME)], "/"), + {ok, Code, _Headers, _Body} = test_request:put( + Url, [{"Content-Type", "text/plain"}, {"Content-Encoding", "gzip"}], + zlib:gzip(Data)), + ?assertEqual(201, Code), + Url. + +gzip(Data) -> + Z = zlib:open(), + ok = zlib:deflateInit(Z, ?COMPRESSION_LEVEL, deflated, 16 + 15, 8, default), + zlib:deflate(Z, Data), + Last = zlib:deflate(Z, [], finish), + ok = zlib:deflateEnd(Z), + ok = zlib:close(Z), + Last. diff --git a/test/couchdb/fixtures/logo.png b/test/couchdb/fixtures/logo.png Binary files differnew file mode 100644 index 000000000..d21ac025b --- /dev/null +++ b/test/couchdb/fixtures/logo.png diff --git a/test/couchdb/test_request.erl b/test/couchdb/test_request.erl index 7abb92f3a..d6725ea06 100644 --- a/test/couchdb/test_request.erl +++ b/test/couchdb/test_request.erl @@ -12,7 +12,7 @@ -module(test_request). --export([get/1, get/2]). +-export([get/1, get/2, put/2, put/3]). -export([request/3, request/4]). get(Url) -> @@ -22,6 +22,13 @@ get(Url, Headers) -> request(get, Url, Headers). +put(Url, Body) -> + request(put, Url, [], Body). + +put(Url, Headers, Body) -> + request(put, Url, Headers, Body). + + request(Method, Url, Headers) -> request(Method, Url, Headers, []). diff --git a/test/etap/140-attachment-comp.t b/test/etap/140-attachment-comp.t deleted file mode 100755 index 6f075ce44..000000000 --- a/test/etap/140-attachment-comp.t +++ /dev/null @@ -1,728 +0,0 @@ -#!/usr/bin/env escript -%% -*- erlang -*- - -% 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. - -test_db_name() -> - <<"couch_test_atts_compression">>. - -main(_) -> - test_util:init_code_path(), - - etap:plan(85), - case (catch test()) of - ok -> - etap:end_tests(); - Other -> - etap:diag(io_lib:format("Test died abnormally: ~p", [Other])), - etap:bail(Other) - end, - ok. - -test() -> - couch_server_sup:start_link(test_util:config_files()), - put(addr, couch_config:get("httpd", "bind_address", "127.0.0.1")), - put(port, integer_to_list(mochiweb_socket_server:get(couch_httpd, port))), - timer:sleep(1000), - couch_server:delete(test_db_name(), []), - couch_db:create(test_db_name(), []), - - couch_config:set("attachments", "compression_level", "8", false), - couch_config:set("attachments", "compressible_types", "text/*", false), - - create_1st_text_att(), - create_1st_png_att(), - create_2nd_text_att(), - create_2nd_png_att(), - - tests_for_1st_text_att(), - tests_for_1st_png_att(), - tests_for_2nd_text_att(), - tests_for_2nd_png_att(), - - create_already_compressed_att(db_url() ++ "/doc_comp_att", "readme.txt"), - test_already_compressed_att(db_url() ++ "/doc_comp_att", "readme.txt"), - - test_create_already_compressed_att_with_invalid_content_encoding( - db_url() ++ "/doc_att_deflate", - "readme.txt", - zlib:compress(test_text_data()), - "deflate" - ), - - % COUCHDB-1711 - avoid weird timng/scheduling/request handling issue - timer:sleep(100), - - test_create_already_compressed_att_with_invalid_content_encoding( - db_url() ++ "/doc_att_compress", - "readme.txt", - % Note: As of OTP R13B04, it seems there's no LZW compression - % (i.e. UNIX compress utility implementation) lib in OTP. - % However there's a simple working Erlang implementation at: - % http://scienceblogs.com/goodmath/2008/01/simple_lempelziv_compression_i.php - test_text_data(), - "compress" - ), - - test_compressible_type_with_parameters(), - - timer:sleep(3000), % to avoid mochiweb socket closed exceptions - couch_server:delete(test_db_name(), []), - couch_server_sup:stop(), - ok. - -db_url() -> - "http://" ++ get(addr) ++ ":" ++ get(port) ++ "/" ++ - binary_to_list(test_db_name()). - -create_1st_text_att() -> - {ok, Code, _Headers, _Body} = test_util:request( - db_url() ++ "/testdoc1/readme.txt", - [{"Content-Type", "text/plain"}], - put, - test_text_data()), - etap:is(Code, 201, "Created text attachment using the standalone api"), - ok. - -create_1st_png_att() -> - {ok, Code, _Headers, _Body} = test_util:request( - db_url() ++ "/testdoc2/icon.png", - [{"Content-Type", "image/png"}], - put, - test_png_data()), - etap:is(Code, 201, "Created png attachment using the standalone api"), - ok. - -% create a text attachment using the non-standalone attachment api -create_2nd_text_att() -> - DocJson = {[ - {<<"_attachments">>, {[ - {<<"readme.txt">>, {[ - {<<"content_type">>, <<"text/plain">>}, - {<<"data">>, base64:encode(test_text_data())} - ]} - }]}} - ]}, - {ok, Code, _Headers, _Body} = test_util:request( - db_url() ++ "/testdoc3", - [{"Content-Type", "application/json"}], - put, - ejson:encode(DocJson)), - etap:is(Code, 201, "Created text attachment using the non-standalone api"), - ok. - -% create a png attachment using the non-standalone attachment api -create_2nd_png_att() -> - DocJson = {[ - {<<"_attachments">>, {[ - {<<"icon.png">>, {[ - {<<"content_type">>, <<"image/png">>}, - {<<"data">>, base64:encode(test_png_data())} - ]} - }]}} - ]}, - {ok, Code, _Headers, _Body} = test_util:request( - db_url() ++ "/testdoc4", - [{"Content-Type", "application/json"}], - put, - ejson:encode(DocJson)), - etap:is(Code, 201, "Created png attachment using the non-standalone api"), - ok. - -create_already_compressed_att(DocUri, AttName) -> - {ok, Code, _Headers, _Body} = test_util:request( - DocUri ++ "/" ++ AttName, - [{"Content-Type", "text/plain"}, {"Content-Encoding", "gzip"}], - put, - zlib:gzip(test_text_data())), - etap:is( - Code, - 201, - "Created already compressed attachment using the standalone api" - ), - ok. - -tests_for_1st_text_att() -> - test_get_1st_text_att_with_accept_encoding_gzip(), - test_get_1st_text_att_without_accept_encoding_header(), - test_get_1st_text_att_with_accept_encoding_deflate(), - test_get_1st_text_att_with_accept_encoding_deflate_only(), - test_get_doc_with_1st_text_att(), - test_1st_text_att_stub(). - -tests_for_1st_png_att() -> - test_get_1st_png_att_without_accept_encoding_header(), - test_get_1st_png_att_with_accept_encoding_gzip(), - test_get_1st_png_att_with_accept_encoding_deflate(), - test_get_doc_with_1st_png_att(), - test_1st_png_att_stub(). - -tests_for_2nd_text_att() -> - test_get_2nd_text_att_with_accept_encoding_gzip(), - test_get_2nd_text_att_without_accept_encoding_header(), - test_get_doc_with_2nd_text_att(), - test_2nd_text_att_stub(). - -tests_for_2nd_png_att() -> - test_get_2nd_png_att_without_accept_encoding_header(), - test_get_2nd_png_att_with_accept_encoding_gzip(), - test_get_doc_with_2nd_png_att(), - test_2nd_png_att_stub(). - -test_get_1st_text_att_with_accept_encoding_gzip() -> - {ok, Code, Headers, Body} = test_util:request( - db_url() ++ "/testdoc1/readme.txt", - [{"Accept-Encoding", "gzip"}], - get), - etap:is(Code, 200, "HTTP response code is 200"), - Gziped = lists:member({"Content-Encoding", "gzip"}, Headers), - etap:is(Gziped, true, "received body is gziped"), - Uncompressed = zlib:gunzip(iolist_to_binary(Body)), - etap:is( - Uncompressed, - test_text_data(), - "received data for the 1st text attachment is ok" - ), - ok. - -test_get_1st_text_att_without_accept_encoding_header() -> - {ok, Code, Headers, Body} = test_util:request( - db_url() ++ "/testdoc1/readme.txt", - [], - get), - etap:is(Code, 200, "HTTP response code is 200"), - Gziped = lists:member({"Content-Encoding", "gzip"}, Headers), - etap:is(Gziped, false, "received body is not gziped"), - etap:is( - iolist_to_binary(Body), - test_text_data(), - "received data for the 1st text attachment is ok" - ), - ok. - -test_get_1st_text_att_with_accept_encoding_deflate() -> - {ok, Code, Headers, Body} = test_util:request( - db_url() ++ "/testdoc1/readme.txt", - [{"Accept-Encoding", "deflate"}], - get), - etap:is(Code, 200, "HTTP response code is 200"), - Gziped = lists:member({"Content-Encoding", "gzip"}, Headers), - etap:is(Gziped, false, "received body is not gziped"), - Deflated = lists:member({"Content-Encoding", "deflate"}, Headers), - etap:is(Deflated, false, "received body is not deflated"), - etap:is( - iolist_to_binary(Body), - test_text_data(), - "received data for the 1st text attachment is ok" - ), - ok. - -test_get_1st_text_att_with_accept_encoding_deflate_only() -> - {ok, Code, _Headers, _Body} = test_util:request( - db_url() ++ "/testdoc1/readme.txt", - [{"Accept-Encoding", "deflate, *;q=0"}], - get), - etap:is( - Code, - 406, - "HTTP response code is 406 for an unsupported content encoding request" - ), - ok. - -test_get_1st_png_att_without_accept_encoding_header() -> - {ok, Code, Headers, Body} = test_util:request( - db_url() ++ "/testdoc2/icon.png", - [], - get), - etap:is(Code, 200, "HTTP response code is 200"), - Encoding = couch_util:get_value("Content-Encoding", Headers), - etap:is(Encoding, undefined, "received body is not gziped"), - etap:is( - iolist_to_binary(Body), - test_png_data(), - "received data for the 1st png attachment is ok" - ), - ok. - -test_get_1st_png_att_with_accept_encoding_gzip() -> - {ok, Code, Headers, Body} = test_util:request( - db_url() ++ "/testdoc2/icon.png", - [{"Accept-Encoding", "gzip"}], - get), - etap:is(Code, 200, "HTTP response code is 200"), - Encoding = couch_util:get_value("Content-Encoding", Headers), - etap:is(Encoding, undefined, "received body is not gziped"), - etap:is( - iolist_to_binary(Body), - test_png_data(), - "received data for the 1st png attachment is ok" - ), - ok. - -test_get_1st_png_att_with_accept_encoding_deflate() -> - {ok, Code, Headers, Body} = test_util:request( - db_url() ++ "/testdoc2/icon.png", - [{"Accept-Encoding", "deflate"}], - get), - etap:is(Code, 200, "HTTP response code is 200"), - Encoding = couch_util:get_value("Content-Encoding", Headers), - etap:is(Encoding, undefined, "received body is in identity form"), - etap:is( - iolist_to_binary(Body), - test_png_data(), - "received data for the 1st png attachment is ok" - ), - ok. - -test_get_doc_with_1st_text_att() -> - {ok, Code, _Headers, Body} = test_util:request( - db_url() ++ "/testdoc1?attachments=true", - [{"Accept", "application/json"}], - get), - etap:is(Code, 200, "HTTP response code is 200"), - Json = ejson:decode(Body), - TextAttJson = couch_util:get_nested_json_value( - Json, - [<<"_attachments">>, <<"readme.txt">>] - ), - TextAttType = couch_util:get_nested_json_value( - TextAttJson, - [<<"content_type">>] - ), - TextAttData = couch_util:get_nested_json_value( - TextAttJson, - [<<"data">>] - ), - etap:is( - TextAttType, - <<"text/plain">>, - "1st text attachment has type text/plain" - ), - %% check the attachment's data is the base64 encoding of the plain text - %% and not the base64 encoding of the gziped plain text - etap:is( - TextAttData, - base64:encode(test_text_data()), - "1st text attachment data is properly base64 encoded" - ), - ok. - -test_1st_text_att_stub() -> - {ok, Code, _Headers, Body} = test_util:request( - db_url() ++ "/testdoc1?att_encoding_info=true", - [], - get), - etap:is(Code, 200, "HTTP response code is 200"), - Json = ejson:decode(Body), - {TextAttJson} = couch_util:get_nested_json_value( - Json, - [<<"_attachments">>, <<"readme.txt">>] - ), - TextAttLength = couch_util:get_value(<<"length">>, TextAttJson), - etap:is( - TextAttLength, - byte_size(test_text_data()), - "1st text attachment stub length matches the uncompressed length" - ), - TextAttEncoding = couch_util:get_value(<<"encoding">>, TextAttJson), - etap:is( - TextAttEncoding, - <<"gzip">>, - "1st text attachment stub has the encoding field set to gzip" - ), - TextAttEncLength = couch_util:get_value(<<"encoded_length">>, TextAttJson), - etap:is( - TextAttEncLength, - iolist_size(zlib:gzip(test_text_data())), - "1st text attachment stub encoded_length matches the compressed length" - ), - ok. - -test_get_doc_with_1st_png_att() -> - {ok, Code, _Headers, Body} = test_util:request( - db_url() ++ "/testdoc2?attachments=true", - [{"Accept", "application/json"}], - get), - etap:is(Code, 200, "HTTP response code is 200"), - Json = ejson:decode(Body), - PngAttJson = couch_util:get_nested_json_value( - Json, - [<<"_attachments">>, <<"icon.png">>] - ), - PngAttType = couch_util:get_nested_json_value( - PngAttJson, - [<<"content_type">>] - ), - PngAttData = couch_util:get_nested_json_value( - PngAttJson, - [<<"data">>] - ), - etap:is(PngAttType, <<"image/png">>, "attachment has type image/png"), - etap:is( - PngAttData, - base64:encode(test_png_data()), - "1st png attachment data is properly base64 encoded" - ), - ok. - -test_1st_png_att_stub() -> - {ok, Code, _Headers, Body} = test_util:request( - db_url() ++ "/testdoc2?att_encoding_info=true", - [{"Accept", "application/json"}], - get), - etap:is(Code, 200, "HTTP response code is 200"), - Json = ejson:decode(Body), - {PngAttJson} = couch_util:get_nested_json_value( - Json, - [<<"_attachments">>, <<"icon.png">>] - ), - PngAttLength = couch_util:get_value(<<"length">>, PngAttJson), - etap:is( - PngAttLength, - byte_size(test_png_data()), - "1st png attachment stub length matches the uncompressed length" - ), - PngEncoding = couch_util:get_value(<<"encoding">>, PngAttJson), - etap:is( - PngEncoding, - undefined, - "1st png attachment stub doesn't have an encoding field" - ), - PngEncLength = couch_util:get_value(<<"encoded_length">>, PngAttJson), - etap:is( - PngEncLength, - undefined, - "1st png attachment stub doesn't have an encoded_length field" - ), - ok. - -test_get_2nd_text_att_with_accept_encoding_gzip() -> - {ok, Code, Headers, Body} = test_util:request( - db_url() ++ "/testdoc3/readme.txt", - [{"Accept-Encoding", "gzip"}], - get), - etap:is(Code, 200, "HTTP response code is 200"), - Gziped = lists:member({"Content-Encoding", "gzip"}, Headers), - etap:is(Gziped, true, "received body is gziped"), - Uncompressed = zlib:gunzip(iolist_to_binary(Body)), - etap:is( - Uncompressed, - test_text_data(), - "received data for the 2nd text attachment is ok" - ), - ok. - -test_get_2nd_text_att_without_accept_encoding_header() -> - {ok, Code, Headers, Body} = test_util:request( - db_url() ++ "/testdoc3/readme.txt", - [], - get), - etap:is(Code, 200, "HTTP response code is 200"), - Gziped = lists:member({"Content-Encoding", "gzip"}, Headers), - etap:is(Gziped, false, "received body is not gziped"), - etap:is( - Body, - test_text_data(), - "received data for the 2nd text attachment is ok" - ), - ok. - -test_get_2nd_png_att_without_accept_encoding_header() -> - {ok, Code, Headers, Body} = test_util:request( - db_url() ++ "/testdoc4/icon.png", - [], - get), - etap:is(Code, 200, "HTTP response code is 200"), - Gziped = lists:member({"Content-Encoding", "gzip"}, Headers), - etap:is(Gziped, false, "received body is not gziped"), - etap:is( - Body, - test_png_data(), - "received data for the 2nd png attachment is ok" - ), - ok. - -test_get_2nd_png_att_with_accept_encoding_gzip() -> - {ok, Code, Headers, Body} = test_util:request( - db_url() ++ "/testdoc4/icon.png", - [{"Accept-Encoding", "gzip"}], - get), - etap:is(Code, 200, "HTTP response code is 200"), - Gziped = lists:member({"Content-Encoding", "gzip"}, Headers), - etap:is(Gziped, false, "received body is not gziped"), - etap:is( - Body, - test_png_data(), - "received data for the 2nd png attachment is ok" - ), - ok. - -test_get_doc_with_2nd_text_att() -> - {ok, Code, _Headers, Body} = test_util:request( - db_url() ++ "/testdoc3?attachments=true", - [{"Accept", "application/json"}], - get), - etap:is(Code, 200, "HTTP response code is 200"), - Json = ejson:decode(Body), - TextAttJson = couch_util:get_nested_json_value( - Json, - [<<"_attachments">>, <<"readme.txt">>] - ), - TextAttType = couch_util:get_nested_json_value( - TextAttJson, - [<<"content_type">>] - ), - TextAttData = couch_util:get_nested_json_value( - TextAttJson, - [<<"data">>] - ), - etap:is(TextAttType, <<"text/plain">>, "attachment has type text/plain"), - %% check the attachment's data is the base64 encoding of the plain text - %% and not the base64 encoding of the gziped plain text - etap:is( - TextAttData, - base64:encode(test_text_data()), - "2nd text attachment data is properly base64 encoded" - ), - ok. - -test_2nd_text_att_stub() -> - {ok, Code, _Headers, Body} = test_util:request( - db_url() ++ "/testdoc3?att_encoding_info=true", - [], - get), - etap:is(Code, 200, "HTTP response code is 200"), - Json = ejson:decode(Body), - {TextAttJson} = couch_util:get_nested_json_value( - Json, - [<<"_attachments">>, <<"readme.txt">>] - ), - TextAttLength = couch_util:get_value(<<"length">>, TextAttJson), - etap:is( - TextAttLength, - byte_size(test_text_data()), - "2nd text attachment stub length matches the uncompressed length" - ), - TextAttEncoding = couch_util:get_value(<<"encoding">>, TextAttJson), - etap:is( - TextAttEncoding, - <<"gzip">>, - "2nd text attachment stub has the encoding field set to gzip" - ), - TextAttEncLength = couch_util:get_value(<<"encoded_length">>, TextAttJson), - etap:is( - TextAttEncLength, - iolist_size(zlib:gzip(test_text_data())), - "2nd text attachment stub encoded_length matches the compressed length" - ), - ok. - -test_get_doc_with_2nd_png_att() -> - {ok, Code, _Headers, Body} = test_util:request( - db_url() ++ "/testdoc4?attachments=true", - [{"Accept", "application/json"}], - get), - etap:is(Code, 200, "HTTP response code is 200"), - Json = ejson:decode(Body), - PngAttJson = couch_util:get_nested_json_value( - Json, - [<<"_attachments">>, <<"icon.png">>] - ), - PngAttType = couch_util:get_nested_json_value( - PngAttJson, - [<<"content_type">>] - ), - PngAttData = couch_util:get_nested_json_value( - PngAttJson, - [<<"data">>] - ), - etap:is(PngAttType, <<"image/png">>, "attachment has type image/png"), - etap:is( - PngAttData, - base64:encode(test_png_data()), - "2nd png attachment data is properly base64 encoded" - ), - ok. - -test_2nd_png_att_stub() -> - {ok, Code, _Headers, Body} = test_util:request( - db_url() ++ "/testdoc4?att_encoding_info=true", - [], - get), - etap:is(Code, 200, "HTTP response code is 200"), - Json = ejson:decode(Body), - {PngAttJson} = couch_util:get_nested_json_value( - Json, - [<<"_attachments">>, <<"icon.png">>] - ), - PngAttLength = couch_util:get_value(<<"length">>, PngAttJson), - etap:is( - PngAttLength, - byte_size(test_png_data()), - "2nd png attachment stub length matches the uncompressed length" - ), - PngEncoding = couch_util:get_value(<<"encoding">>, PngAttJson), - etap:is( - PngEncoding, - undefined, - "2nd png attachment stub doesn't have an encoding field" - ), - PngEncLength = couch_util:get_value(<<"encoded_length">>, PngAttJson), - etap:is( - PngEncLength, - undefined, - "2nd png attachment stub doesn't have an encoded_length field" - ), - ok. - -test_already_compressed_att(DocUri, AttName) -> - test_get_already_compressed_att_with_accept_gzip(DocUri, AttName), - test_get_already_compressed_att_without_accept(DocUri, AttName), - test_get_already_compressed_att_stub(DocUri, AttName). - -test_get_already_compressed_att_with_accept_gzip(DocUri, AttName) -> - {ok, Code, Headers, Body} = test_util:request( - DocUri ++ "/" ++ AttName, - [{"Accept-Encoding", "gzip"}], - get), - etap:is(Code, 200, "HTTP response code is 200"), - Gziped = lists:member({"Content-Encoding", "gzip"}, Headers), - etap:is(Gziped, true, "received body is gziped"), - etap:is( - Body, - zlib:gzip(test_text_data()), - "received data for the already compressed attachment is ok" - ), - ok. - -test_get_already_compressed_att_without_accept(DocUri, AttName) -> - {ok, Code, Headers, Body} = test_util:request( - DocUri ++ "/" ++ AttName, - [], - get), - etap:is(Code, 200, "HTTP response code is 200"), - Gziped = lists:member({"Content-Encoding", "gzip"}, Headers), - etap:is(Gziped, false, "received body is not gziped"), - etap:is( - Body, - test_text_data(), - "received data for the already compressed attachment is ok" - ), - ok. - -test_get_already_compressed_att_stub(DocUri, AttName) -> - {ok, Code, _Headers, Body} = test_util:request( - DocUri ++ "?att_encoding_info=true", - [], - get), - etap:is(Code, 200, "HTTP response code is 200"), - Json = ejson:decode(Body), - {AttJson} = couch_util:get_nested_json_value( - Json, - [<<"_attachments">>, iolist_to_binary(AttName)] - ), - AttLength = couch_util:get_value(<<"length">>, AttJson), - etap:is( - AttLength, - iolist_size((zlib:gzip(test_text_data()))), - "Already compressed attachment stub length matches the " - "compressed length" - ), - Encoding = couch_util:get_value(<<"encoding">>, AttJson), - etap:is( - Encoding, - <<"gzip">>, - "Already compressed attachment stub has the encoding field set to gzip" - ), - EncLength = couch_util:get_value(<<"encoded_length">>, AttJson), - etap:is( - EncLength, - AttLength, - "Already compressed attachment stub encoded_length matches the " - "length field value" - ), - ok. - -test_create_already_compressed_att_with_invalid_content_encoding( - DocUri, AttName, AttData, Encoding) -> - {ok, Code, _Headers, _Body} = test_util:request( - DocUri ++ "/" ++ AttName, - [{"Content-Encoding", Encoding}, {"Content-Type", "text/plain"}], - put, - AttData), - etap:is( - Code, - 415, - "Couldn't create an already compressed attachment using the " - "unsupported encoding '" ++ Encoding ++ "'" - ), - ok. - -test_compressible_type_with_parameters() -> - {ok, Code, _Headers, _Body} = test_util:request( - db_url() ++ "/testdoc5/readme.txt", - [{"Content-Type", "text/plain; charset=UTF-8"}], - put, - test_text_data()), - etap:is(Code, 201, "Created text attachment with MIME type " - "'text/plain; charset=UTF-8' using the standalone api"), - {ok, Code2, Headers2, Body} = test_util:request( - db_url() ++ "/testdoc5/readme.txt", - [{"Accept-Encoding", "gzip"}], - get), - etap:is(Code2, 200, "HTTP response code is 200"), - Gziped = lists:member({"Content-Encoding", "gzip"}, Headers2), - etap:is(Gziped, true, "received body is gziped"), - Uncompressed = zlib:gunzip(iolist_to_binary(Body)), - etap:is(Uncompressed, test_text_data(), "received data is gzipped"), - {ok, Code3, _Headers3, Body3} = test_util:request( - db_url() ++ "/testdoc5?att_encoding_info=true", - [], - get), - etap:is(Code3, 200, "HTTP response code is 200"), - Json = ejson:decode(Body3), - {TextAttJson} = couch_util:get_nested_json_value( - Json, - [<<"_attachments">>, <<"readme.txt">>] - ), - TextAttLength = couch_util:get_value(<<"length">>, TextAttJson), - etap:is( - TextAttLength, - byte_size(test_text_data()), - "text attachment stub length matches the uncompressed length" - ), - TextAttEncoding = couch_util:get_value(<<"encoding">>, TextAttJson), - etap:is( - TextAttEncoding, - <<"gzip">>, - "text attachment stub has the encoding field set to gzip" - ), - TextAttEncLength = couch_util:get_value(<<"encoded_length">>, TextAttJson), - etap:is( - TextAttEncLength, - iolist_size(zlib:gzip(test_text_data())), - "text attachment stub encoded_length matches the compressed length" - ), - ok. - -test_png_data() -> - {ok, Data} = file:read_file( - test_util:source_file("share/www/image/logo.png") - ), - Data. - -test_text_data() -> - {ok, Data} = file:read_file( - test_util:source_file("README.rst") - ), - Data. diff --git a/test/etap/Makefile.am b/test/etap/Makefile.am index f54e927e0..94ff6f2f7 100644 --- a/test/etap/Makefile.am +++ b/test/etap/Makefile.am @@ -36,7 +36,6 @@ fixture_files = \ fixtures/test.couch tap_files = \ - 140-attachment-comp.t \ 150-invalid-view-seq.t \ 160-vhosts.t \ 170-os-daemons.es \ |