%-*-Mode:erlang;coding:utf-8;tab-width:4;c-basic-offset:4;indent-tabs-mode:()-*- % ex: set ft=erlang fenc=utf-8 sts=4 ts=4 sw=4 et nomod: %%%------------------------------------------------------------------------ %%% @doc %%% ==CloudI Service Filesystem Tests== %%% @end %%% %%% MIT License %%% %%% Copyright (c) 2014-2021 Michael Truog %%% %%% Permission is hereby granted, free of charge, to any person obtaining a %%% copy of this software and associated documentation files (the "Software"), %%% to deal in the Software without restriction, including without limitation %%% the rights to use, copy, modify, merge, publish, distribute, sublicense, %%% and/or sell copies of the Software, and to permit persons to whom the %%% Software is furnished to do so, subject to the following conditions: %%% %%% The above copyright notice and this permission notice shall be included in %%% all copies or substantial portions of the Software. %%% %%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR %%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, %%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE %%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING %%% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER %%% DEALINGS IN THE SOFTWARE. %%% %%% @author Michael Truog %%% @copyright 2014-2021 Michael Truog %%% @version 2.0.2 {@date} {@time} %%%------------------------------------------------------------------------ -module(cloudi_service_filesystem_SUITE). %% CT callbacks -export([all/0, groups/0, suite/0, init_per_suite/1, end_per_suite/1, group/1, init_per_group/2, end_per_group/2, init_per_testcase/2, end_per_testcase/2]). %% test callbacks -export([t_filesystem_basic_read_1/1, t_filesystem_basic_read_wcache_1/1, t_filesystem_basic_write_truncate_1/1, t_filesystem_basic_write_truncate_wcache_1/1, t_filesystem_basic_write_append_1/1, t_filesystem_basic_write_append_wcache_1/1, t_filesystem_basic_read_cache_1/1, t_filesystem_size_limit_1/1, t_filesystem_size_limit_2/1]). -include_lib("common_test/include/ct.hrl"). -include_lib("cloudi_core/include/cloudi_logger.hrl"). -ifndef(CLOUDI_TEST_TIMEOUT). -define(CLOUDI_TEST_TIMEOUT, 10). % seconds -endif. -define(SERVICE_PREFIX1, "/filesystem/"). % ASCII_FILE created with: file:write_file("ASCII.bin", lists:seq(0, 126)). -define(ASCII_FILE, "ASCII.bin"). -define(WRITABLE_FILENAME1, "filename1.txt"). -define(TIMEOUT, (?CLOUDI_TEST_TIMEOUT * 1000 div 2)). -define(REFRESH, (erlang:round(?TIMEOUT * 2.5) div 1000)). %%%------------------------------------------------------------------------ %%% Callback functions from CT %%%------------------------------------------------------------------------ all() -> [{group, filesystem_basic_1}]. groups() -> [{filesystem_basic_1, [], [t_filesystem_basic_read_1, t_filesystem_basic_read_wcache_1, t_filesystem_basic_write_truncate_1, t_filesystem_basic_write_truncate_wcache_1, t_filesystem_basic_write_append_1, t_filesystem_basic_write_append_wcache_1, t_filesystem_basic_read_cache_1, t_filesystem_size_limit_1, t_filesystem_size_limit_2]}]. suite() -> [{ct_hooks, [cth_surefire]}, {timetrap, {seconds, ?CLOUDI_TEST_TIMEOUT}}]. init_per_suite(Config) -> Refresh = ?REFRESH, Refresh = erlang:round(?TIMEOUT * 2.5) div 1000, ok = reltool_util:application_start(cloudi_core, [], infinity), TmpDir = os:getenv("TMPDIR", "/tmp"), TmpDir1 = TmpDir ++ "/cloudi_service_filesystem_test_dir1/", TmpDir2 = TmpDir ++ "/cloudi_service_filesystem_test_dir2/", ok = filelib:ensure_dir(TmpDir1), ok = filelib:ensure_dir(TmpDir2), [{tmpdir1, TmpDir1}, {tmpdir2, TmpDir2} | Config]. end_per_suite(Config) -> ok = reltool_util:application_stop(cloudi_core), TmpDir1Rm = os:cmd("rmdir " ++ ?config(tmpdir1, Config)), if TmpDir1Rm == [] -> ok; true -> ?LOG_ERROR("~s", [TmpDir1Rm]) end, TmpDir2Rm = os:cmd("rmdir " ++ ?config(tmpdir2, Config)), if TmpDir2Rm == [] -> ok; true -> ?LOG_ERROR("~s", [TmpDir2Rm]) end, ok. group(_GroupName) -> []. init_per_group(_GroupName, Config) -> Config. end_per_group(_GroupName, Config) -> Config. init_per_testcase(TestCase, Config) when (TestCase =:= t_filesystem_basic_read_1) -> {ok, ServiceIds} = cloudi_service_api:services_add([ % using proplist configuration format, not the tuple/record format [{prefix, ?SERVICE_PREFIX1}, {module, cloudi_service_filesystem}, {args, [{directory, "${TEST_DIR}"}, {use_content_disposition, true}]}, {dest_refresh, none}, {timeout_init, ?TIMEOUT}, {timeout_sync, ?TIMEOUT}] ], infinity), [{service_ids, ServiceIds} | Config]; init_per_testcase(TestCase, Config) when (TestCase =:= t_filesystem_basic_read_wcache_1) -> {ok, ServiceIds} = cloudi_service_api:services_add([ % using proplist configuration format, not the tuple/record format [{prefix, ?SERVICE_PREFIX1}, {module, cloudi_service_filesystem}, {args, [{directory, "${TEST_DIR}"}, {cache, 1}, {refresh, ?REFRESH}, {use_content_disposition, true}]}, {dest_refresh, none}, {timeout_init, ?TIMEOUT}, {timeout_sync, ?TIMEOUT}] ], infinity), [{service_ids, ServiceIds} | Config]; init_per_testcase(TestCase, Config) when (TestCase =:= t_filesystem_basic_write_truncate_1) -> ok = file:write_file(writable_filepath1(Config), <<>>), {ok, ServiceIds} = cloudi_service_api:services_add([ % using proplist configuration format, not the tuple/record format [{prefix, ?SERVICE_PREFIX1}, {module, cloudi_service_filesystem}, {args, [{directory, ?config(tmpdir1, Config)}, {write_truncate, [?SERVICE_PREFIX1 ?WRITABLE_FILENAME1]}, {use_content_disposition, true}]}, {dest_refresh, none}, {timeout_init, ?TIMEOUT}, {timeout_sync, ?TIMEOUT}] ], infinity), [{service_ids, ServiceIds} | Config]; init_per_testcase(TestCase, Config) when (TestCase =:= t_filesystem_basic_write_truncate_wcache_1) -> ok = file:write_file(writable_filepath1(Config), <<>>), {ok, ServiceIds} = cloudi_service_api:services_add([ % using proplist configuration format, not the tuple/record format [{prefix, ?SERVICE_PREFIX1}, {module, cloudi_service_filesystem}, {args, [{directory, ?config(tmpdir1, Config)}, {cache, 1}, {refresh, ?REFRESH}, {write_truncate, [?SERVICE_PREFIX1 ?WRITABLE_FILENAME1]}, {use_content_disposition, true}]}, {dest_refresh, none}, {timeout_init, ?TIMEOUT}, {timeout_sync, ?TIMEOUT}] ], infinity), [{service_ids, ServiceIds} | Config]; init_per_testcase(TestCase, Config) when (TestCase =:= t_filesystem_basic_write_append_1) -> ok = file:write_file(writable_filepath1(Config), <<>>), {ok, ServiceIds} = cloudi_service_api:services_add([ % using proplist configuration format, not the tuple/record format [{prefix, ?SERVICE_PREFIX1}, {module, cloudi_service_filesystem}, {args, [{directory, ?config(tmpdir1, Config)}, {write_append, [?SERVICE_PREFIX1 ?WRITABLE_FILENAME1]}, {use_content_disposition, true}]}, {dest_refresh, none}, {timeout_init, ?TIMEOUT}, {timeout_sync, ?TIMEOUT}] ], infinity), [{service_ids, ServiceIds} | Config]; init_per_testcase(TestCase, Config) when (TestCase =:= t_filesystem_basic_write_append_wcache_1) -> ok = file:write_file(writable_filepath1(Config), <<>>), {ok, ServiceIds} = cloudi_service_api:services_add([ % using proplist configuration format, not the tuple/record format [{prefix, ?SERVICE_PREFIX1}, {module, cloudi_service_filesystem}, {args, [{directory, ?config(tmpdir1, Config)}, {cache, 1}, {refresh, ?REFRESH}, {write_append, [?SERVICE_PREFIX1 ?WRITABLE_FILENAME1]}, {use_content_disposition, true}]}, {dest_refresh, none}, {timeout_init, ?TIMEOUT}, {timeout_sync, ?TIMEOUT}] ], infinity), [{service_ids, ServiceIds} | Config]; init_per_testcase(TestCase, Config) when (TestCase =:= t_filesystem_basic_read_cache_1) -> {ok, ServiceIds} = cloudi_service_api:services_add([ % using proplist configuration format, not the tuple/record format [{prefix, ?SERVICE_PREFIX1}, {module, cloudi_service_filesystem}, {args, [{directory, "${TEST_DIR}"}, {cache, ?REFRESH}, {refresh, ?REFRESH}, {use_content_disposition, true}]}, {dest_refresh, none}, {timeout_init, ?TIMEOUT}, {timeout_sync, ?TIMEOUT}] ], infinity), [{service_ids, ServiceIds} | Config]; init_per_testcase(TestCase, Config) when (TestCase =:= t_filesystem_size_limit_1) -> _ = file:delete(writable_filepath2(Config)), {ok, ServiceIds} = cloudi_service_api:services_add([ % using proplist configuration format, not the tuple/record format [{prefix, ?SERVICE_PREFIX1}, {module, cloudi_service_filesystem}, {args, [{directory, ?config(tmpdir2, Config)}, {files_size, 2}, % Kb {write_append, [?SERVICE_PREFIX1 ?WRITABLE_FILENAME1]}, {use_content_disposition, true}]}, {dest_refresh, none}, {timeout_init, ?TIMEOUT}, {timeout_sync, ?TIMEOUT}] ], infinity), [{service_ids, ServiceIds} | Config]; init_per_testcase(TestCase, Config) when (TestCase =:= t_filesystem_size_limit_2) -> _ = file:delete(writable_filepath2(Config)), {ok, ServiceIds} = cloudi_service_api:services_add([ % using proplist configuration format, not the tuple/record format [{prefix, ?SERVICE_PREFIX1}, {module, cloudi_service_filesystem}, {args, [{directory, ?config(tmpdir2, Config)}, {files_size, 1}, % Kb {write_truncate, [?SERVICE_PREFIX1 ?WRITABLE_FILENAME1]}, {use_content_disposition, true}]}, {dest_refresh, none}, {timeout_init, ?TIMEOUT}, {timeout_sync, ?TIMEOUT}] ], infinity), [{service_ids, ServiceIds} | Config]. end_per_testcase(TestCase, Config) -> {value, {_, ServiceIds}, NewConfig} = lists:keytake(service_ids, 1, Config), ok = cloudi_service_api:services_remove(ServiceIds, infinity), if TestCase =:= t_filesystem_basic_write_truncate_1; TestCase =:= t_filesystem_basic_write_truncate_wcache_1; TestCase =:= t_filesystem_basic_write_append_1; TestCase =:= t_filesystem_basic_write_append_wcache_1 -> ok = file:delete(writable_filepath1(Config)); TestCase =:= t_filesystem_size_limit_1; TestCase =:= t_filesystem_size_limit_2 -> ok = file:delete(writable_filepath2(Config)); true -> ok end, NewConfig. %%%------------------------------------------------------------------------ %%% test cases %%%------------------------------------------------------------------------ t_filesystem_basic_read_1(_Config) -> Context0 = cloudi:new(), ServiceNameHead = ?SERVICE_PREFIX1 ++ ?ASCII_FILE ++ "/head", ServiceNameGet = ?SERVICE_PREFIX1 ++ ?ASCII_FILE ++ "/get", ASCII = erlang:list_to_binary(lists:seq(0, 126)), Request = <<>>, Timeout = undefined, % default Priority = undefined, % default {{ok, [{<<"content-type">>, <<"application/octet-stream">>}, {<<"content-disposition">>, <<"attachment; filename=\"ASCII.bin\"">>}, {<<"etag">>, ETag}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], ASCII}, Context1} = cloudi:send_sync(Context0, ServiceNameGet, <<>>, Request, Timeout, Priority), RequestInfo1 = [{<<"range">>, % "Hello World!" test <<"bytes=" "72-72,101-101,108-108,108-108,111-111," "32-32," "87-87,111-111,114-114,108-108,100-100," "33-33">>}], {{ok, [{<<"status">>, <<"206">>}, {<<"content-type">>, <<"multipart/byteranges">>}, {<<"etag">>, ETag}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], <<>>}, Context2} = cloudi:send_sync(Context1, ServiceNameHead, RequestInfo1, Request, Timeout, Priority), BSize = 512, % 64 characters for a boundary, from cowlib {{ok, [{<<"status">>, <<"206">>}, {<<"content-type">>, <<"multipart/byteranges; boundary=", Boundary1:BSize/bitstring>>}, {<<"etag">>, ETag}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], <<"\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 72-72/127\r\n\r\n" "H" "\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 101-101/127\r\n\r\n" "e" "\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 108-108/127\r\n\r\n" "l" "\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 108-108/127\r\n\r\n" "l" "\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 111-111/127\r\n\r\n" "o" "\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 32-32/127\r\n\r\n" " " "\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 87-87/127\r\n\r\n" "W" "\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 111-111/127\r\n\r\n" "o" "\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 114-114/127\r\n\r\n" "r" "\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 108-108/127\r\n\r\n" "l" "\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 100-100/127\r\n\r\n" "d" "\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 33-33/127\r\n\r\n" "!" "\r\n--", Boundary1:BSize/bitstring, "--">>}, Context3} = cloudi:send_sync(Context2, ServiceNameGet, RequestInfo1, Request, Timeout, Priority), RequestInfo2 = [{<<"range">>, % "abc" test <<"bytes=" "97-99">>}, {<<"if-range">>, ETag}], {{ok, [{<<"status">>, <<"206">>}, {<<"content-type">>,<<"application/octet-stream">>}, {<<"content-range">>, <<"bytes 97-99/127">>}, {<<"etag">>, ETag}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], <<"abc">>}, Context4} = cloudi:send_sync(Context3, ServiceNameGet, RequestInfo2, Request, Timeout, Priority), RequestInfo3 = [{<<"range">>, % "abc" test <<"bytes=" "97-99">>}, {<<"if-range">>, LastModified}], {{ok, [{<<"status">>, <<"206">>}, {<<"content-type">>,<<"application/octet-stream">>}, {<<"content-range">>, <<"bytes 97-99/127">>}, {<<"etag">>, ETag}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], <<"abc">>}, Context5} = cloudi:send_sync(Context4, ServiceNameGet, RequestInfo3, Request, Timeout, Priority), RequestInfo4 = [{<<"range">>, % "abc" test <<"bytes=" "97-99">>}, {<<"if-range">>, <>)/binary>>}], {{ok, [{<<"content-type">>, <<"application/octet-stream">>}, {<<"content-disposition">>, <<"attachment; filename=\"ASCII.bin\"">>}, {<<"etag">>, ETag}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], % bad ETag provides the whole ASCII file ASCII}, Context6} = cloudi:send_sync(Context5, ServiceNameGet, RequestInfo4, Request, Timeout, Priority), % alter the last-modified date to have the wrong seconds value <> = LastModified, LastModified1Future = erlang:integer_to_binary( (erlang:binary_to_integer(LastModified1) + 1) rem 60), LastModified1New = if byte_size(LastModified1Future) == 1 -> <<"0", LastModified1Future/binary>>; true -> LastModified1Future end, LastModifiedFake = <>, RequestInfo5 = [{<<"range">>, % "abc" test <<"bytes=" "97-99">>}, {<<"if-range">>, LastModifiedFake}], {{ok, [{<<"content-type">>, <<"application/octet-stream">>}, {<<"content-disposition">>, <<"attachment; filename=\"ASCII.bin\"">>}, {<<"etag">>, ETag}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], % bad LastModified provides the whole ASCII file ASCII}, Context7} = cloudi:send_sync(Context6, ServiceNameGet, RequestInfo5, Request, Timeout, Priority), RequestInfo6 = [{<<"range">>, % "{|}~" test <<"bytes=" "-4">>}], {{ok, [{<<"status">>, <<"206">>}, {<<"content-type">>,<<"application/octet-stream">>}, {<<"content-range">>, <<"bytes 123-126/127">>}, {<<"etag">>, ETag}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], <<"{|}~">>}, _} = cloudi:send_sync(Context7, ServiceNameGet, RequestInfo6, Request, Timeout, Priority), ok. t_filesystem_basic_read_wcache_1(_Config) -> Context0 = cloudi:new(), ServiceNameHead = ?SERVICE_PREFIX1 ++ ?ASCII_FILE ++ "/head", ServiceNameGet = ?SERVICE_PREFIX1 ++ ?ASCII_FILE ++ "/get", ASCII = erlang:list_to_binary(lists:seq(0, 126)), Request = <<>>, Timeout = undefined, % default Priority = undefined, % default {{ok, [{<<"content-type">>, <<"application/octet-stream">>}, {<<"content-disposition">>, <<"attachment; filename=\"ASCII.bin\"">>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], ASCII}, Context1} = cloudi:send_sync(Context0, ServiceNameGet, <<>>, Request, Timeout, Priority), RequestInfo1 = [{<<"range">>, % "Hello World!" test <<"bytes=" "72-72,101-101,108-108,108-108,111-111," "32-32," "87-87,111-111,114-114,108-108,100-100," "33-33">>}], {{ok, [{<<"status">>, <<"206">>}, {<<"content-type">>, <<"multipart/byteranges">>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], <<>>}, Context2} = cloudi:send_sync(Context1, ServiceNameHead, RequestInfo1, Request, Timeout, Priority), BSize = 512, % 64 characters for a boundary, from cowlib {{ok, [{<<"status">>, <<"206">>}, {<<"content-type">>, <<"multipart/byteranges; boundary=", Boundary1:BSize/bitstring>>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], <<"\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 72-72/127\r\n\r\n" "H" "\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 101-101/127\r\n\r\n" "e" "\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 108-108/127\r\n\r\n" "l" "\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 108-108/127\r\n\r\n" "l" "\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 111-111/127\r\n\r\n" "o" "\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 32-32/127\r\n\r\n" " " "\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 87-87/127\r\n\r\n" "W" "\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 111-111/127\r\n\r\n" "o" "\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 114-114/127\r\n\r\n" "r" "\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 108-108/127\r\n\r\n" "l" "\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 100-100/127\r\n\r\n" "d" "\r\n--", Boundary1:BSize/bitstring, "\r\ncontent-range: bytes 33-33/127\r\n\r\n" "!" "\r\n--", Boundary1:BSize/bitstring, "--">>}, Context3} = cloudi:send_sync(Context2, ServiceNameGet, RequestInfo1, Request, Timeout, Priority), RequestInfo2 = [{<<"range">>, % "abc" test <<"bytes=" "97-99">>}, {<<"if-range">>, ETag}], {{ok, [{<<"status">>, <<"206">>}, {<<"content-type">>,<<"application/octet-stream">>}, {<<"content-range">>, <<"bytes 97-99/127">>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], <<"abc">>}, Context4} = cloudi:send_sync(Context3, ServiceNameGet, RequestInfo2, Request, Timeout, Priority), RequestInfo3 = [{<<"range">>, % "abc" test <<"bytes=" "97-99">>}, {<<"if-range">>, LastModified}], {{ok, [{<<"status">>, <<"206">>}, {<<"content-type">>,<<"application/octet-stream">>}, {<<"content-range">>, <<"bytes 97-99/127">>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], <<"abc">>}, Context5} = cloudi:send_sync(Context4, ServiceNameGet, RequestInfo3, Request, Timeout, Priority), RequestInfo4 = [{<<"range">>, % "abc" test <<"bytes=" "97-99">>}, {<<"if-range">>, <>)/binary>>}], {{ok, [{<<"content-type">>, <<"application/octet-stream">>}, {<<"content-disposition">>, <<"attachment; filename=\"ASCII.bin\"">>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], % bad ETag provides the whole ASCII file ASCII}, Context6} = cloudi:send_sync(Context5, ServiceNameGet, RequestInfo4, Request, Timeout, Priority), % alter the last-modified date to have the wrong seconds value <> = LastModified, LastModified1Future = erlang:integer_to_binary( (erlang:binary_to_integer(LastModified1) + 1) rem 60), LastModified1New = if byte_size(LastModified1Future) == 1 -> <<"0", LastModified1Future/binary>>; true -> LastModified1Future end, LastModifiedFake = <>, RequestInfo5 = [{<<"range">>, % "abc" test <<"bytes=" "97-99">>}, {<<"if-range">>, LastModifiedFake}], {{ok, [{<<"content-type">>, <<"application/octet-stream">>}, {<<"content-disposition">>, <<"attachment; filename=\"ASCII.bin\"">>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], % bad LastModified provides the whole ASCII file ASCII}, Context7}= cloudi:send_sync(Context6, ServiceNameGet, RequestInfo5, Request, Timeout, Priority), RequestInfo6 = [{<<"range">>, % "{|}~" test <<"bytes=" "-4">>}], {{ok, [{<<"status">>, <<"206">>}, {<<"content-type">>,<<"application/octet-stream">>}, {<<"content-range">>, <<"bytes 123-126/127">>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], <<"{|}~">>}, _}= cloudi:send_sync(Context7, ServiceNameGet, RequestInfo6, Request, Timeout, Priority), ok. t_filesystem_basic_write_truncate_1(Config) -> Context0 = cloudi:new(), ServiceNameGet = ?SERVICE_PREFIX1 ++ ?WRITABLE_FILENAME1 ++ "/get", ServiceNamePut = ?SERVICE_PREFIX1 ++ ?WRITABLE_FILENAME1 ++ "/put", Timeout = undefined, % default Priority = undefined, % default {ok, <<>>} = file:read_file(writable_filepath1(Config)), {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"etag">>, ETag0}, {<<"last-modified">>, LastModified0}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], <<>>}, Context1} = cloudi:send_sync(Context0, ServiceNameGet, <<>>, <<>>, Timeout, Priority), Response1 = <<"Hello">>, {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"etag">>, ETag1}, {<<"last-modified">>, LastModified1}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], Response1}, Context2} = cloudi:send_sync(Context1, ServiceNamePut, <<>>, Response1, Timeout, Priority), Response2 = <<"Hello World!">>, {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"etag">>, ETag2}, {<<"last-modified">>, LastModified2}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], Response2}, Context3} = cloudi:send_sync(Context2, ServiceNamePut, <<>>, Response2, Timeout, Priority), true = ETag0 /= ETag1, true = LastModified0 =< LastModified1, true = ETag1 /= ETag2, true = LastModified1 =< LastModified2, {ok, Response2} = file:read_file(writable_filepath1(Config)), {{ok, [{<<"status">>, <<"400">>}], <<>>}, _} = cloudi:send_sync(Context3, ServiceNamePut, [{<<"range">>, <<"bytes=-6">>}], <<"Error!">>, Timeout, Priority), ok. t_filesystem_basic_write_truncate_wcache_1(Config) -> Context0 = cloudi:new(), ServiceNameGet = ?SERVICE_PREFIX1 ++ ?WRITABLE_FILENAME1 ++ "/get", ServiceNamePut = ?SERVICE_PREFIX1 ++ ?WRITABLE_FILENAME1 ++ "/put", Timeout = undefined, % default Priority = undefined, % default {ok, <<>>} = file:read_file(writable_filepath1(Config)), {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag0}, {<<"last-modified">>, LastModified0}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], <<>>}, Context1} = cloudi:send_sync(Context0, ServiceNameGet, <<>>, <<>>, Timeout, Priority), Response1 = <<"Hello">>, {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag1}, {<<"last-modified">>, LastModified1}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], Response1}, Context2} = cloudi:send_sync(Context1, ServiceNamePut, <<>>, Response1, Timeout, Priority), Response2 = <<"Hello World!">>, {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag2}, {<<"last-modified">>, LastModified2}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], Response2}, Context3} = cloudi:send_sync(Context2, ServiceNamePut, <<>>, Response2, Timeout, Priority), true = ETag0 /= ETag1, true = LastModified0 =< LastModified1, true = ETag1 /= ETag2, true = LastModified1 =< LastModified2, {ok, Response2} = file:read_file(writable_filepath1(Config)), {{ok, [{<<"status">>, <<"400">>}], <<>>}, _} = cloudi:send_sync(Context3, ServiceNamePut, [{<<"range">>, <<"bytes=-6">>}], <<"Error!">>, Timeout, Priority), ok. t_filesystem_basic_write_append_1(Config) -> Context0 = cloudi:new(), ServiceNameGet = ?SERVICE_PREFIX1 ++ ?WRITABLE_FILENAME1 ++ "/get", ServiceNamePost = ?SERVICE_PREFIX1 ++ ?WRITABLE_FILENAME1 ++ "/post", Timeout = undefined, % default Priority = undefined, % default {ok, <<>>} = file:read_file(writable_filepath1(Config)), {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"etag">>, ETag0}, {<<"last-modified">>, LastModified0}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], <<>>}, Context1} = cloudi:send_sync(Context0, ServiceNameGet, <<>>, <<>>, Timeout, Priority), Request1 = <<"The quick brown fox tripped">>, {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"etag">>, ETag1}, {<<"last-modified">>, LastModified1}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], Request1}, Context2} = cloudi:send_sync(Context1, ServiceNamePost, <<>>, Request1, Timeout, Priority), RequestInfo2 = [{<<"range">>, <<"bytes=" "-7">>}], Request2 = <<"jumps over the lazy dog">>, Response2 = <<"The quick brown fox jumps over the lazy dog">>, {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"etag">>, ETag2}, {<<"last-modified">>, LastModified2}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], Response2}, Context3} = cloudi:send_sync(Context2, ServiceNamePost, RequestInfo2, Request2, Timeout, Priority), true = ETag0 /= ETag1, true = LastModified0 =< LastModified1, true = ETag1 /= ETag2, true = LastModified1 =< LastModified2, RequestInfo3 = [{<<"range">>, <<"bytes=" "10-14">>}], Request3 = <<"red">>, Response3 = <<"The quick red fox jumps over the lazy dog">>, {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"etag">>, ETag3}, {<<"last-modified">>, LastModified3}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], Response3}, Context4} = cloudi:send_sync(Context3, ServiceNamePost, RequestInfo3, Request3, Timeout, Priority), true = ETag2 /= ETag3, true = LastModified2 =< LastModified3, RequestInfo4 = [{<<"range">>, <<"bytes=" "22-22">>}], Request4 = <<"ed">>, Response4 = <<"The quick red fox jumped over the lazy dog">>, {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"etag">>, ETag4}, {<<"last-modified">>, LastModified4}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], Response4}, Context5} = cloudi:send_sync(Context4, ServiceNamePost, RequestInfo4, Request4, Timeout, Priority), true = ETag3 /= ETag4, true = LastModified3 =< LastModified4, RequestInfo5 = [{<<"range">>, <<"bytes=" "42-42">>}], Request5 = <<"s.">>, Response5 = <<"The quick red fox jumped over the lazy dogs.">>, {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"etag">>, ETag5}, {<<"last-modified">>, LastModified5}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], Response5}, Context6} = cloudi:send_sync(Context5, ServiceNamePost, RequestInfo5, Request5, Timeout, Priority), true = ETag4 /= ETag5, true = LastModified4 =< LastModified5, RequestInfo6 = [{<<"range">>, <<"bytes=" "45-44">>}], {{ok, [{<<"status">>, <<"416">>}, {<<"content-range">>, <<"bytes */44">>}, {<<"accept-ranges">>, <<"bytes">>}], <<>>}, Context7} = cloudi:send_sync(Context6, ServiceNamePost, RequestInfo6, <<" Ignore this data!">>, Timeout, Priority), RequestInfo7 = [{<<"range">>, <<"bytes=" "44-44">>}], Request7 = <<" The fox later became a Hollywood actor.">>, Response7 = <<"The quick red fox jumped over the lazy dogs.", Request7/binary>>, {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"etag">>, ETag7}, {<<"last-modified">>, LastModified7}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], Response7}, Context8} = cloudi:send_sync(Context7, ServiceNamePost, RequestInfo7, Request7, Timeout, Priority), true = ETag5 /= ETag7, true = LastModified5 =< LastModified7, Request8 = <<" The end.">>, Response8 = <>, {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"etag">>, ETag8}, {<<"last-modified">>, LastModified8}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], Response8}, _} = cloudi:send_sync(Context8, ServiceNamePost, <<>>, Request8, Timeout, Priority), true = ETag7 /= ETag8, true = LastModified7 =< LastModified8, {ok, Response8} = file:read_file(writable_filepath1(Config)), ok. t_filesystem_basic_write_append_wcache_1(Config) -> Context0 = cloudi:new(), ServiceNameGet = ?SERVICE_PREFIX1 ++ ?WRITABLE_FILENAME1 ++ "/get", ServiceNamePost = ?SERVICE_PREFIX1 ++ ?WRITABLE_FILENAME1 ++ "/post", Timeout = undefined, % default Priority = undefined, % default {ok, <<>>} = file:read_file(writable_filepath1(Config)), {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag0}, {<<"last-modified">>, LastModified0}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], <<>>}, Context1} = cloudi:send_sync(Context0, ServiceNameGet, <<>>, <<>>, Timeout, Priority), Request1 = <<"The quick brown fox tripped">>, {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag1}, {<<"last-modified">>, LastModified1}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], Request1}, Context2} = cloudi:send_sync(Context1, ServiceNamePost, <<>>, Request1, Timeout, Priority), RequestInfo2 = [{<<"range">>, <<"bytes=" "-7">>}], Request2 = <<"jumps over the lazy dog">>, Response2 = <<"The quick brown fox jumps over the lazy dog">>, {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag2}, {<<"last-modified">>, LastModified2}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], Response2}, Context3} = cloudi:send_sync(Context2, ServiceNamePost, RequestInfo2, Request2, Timeout, Priority), true = ETag0 /= ETag1, true = LastModified0 =< LastModified1, true = ETag1 /= ETag2, true = LastModified1 =< LastModified2, RequestInfo3 = [{<<"range">>, <<"bytes=" "10-14">>}], Request3 = <<"red">>, Response3 = <<"The quick red fox jumps over the lazy dog">>, {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag3}, {<<"last-modified">>, LastModified3}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], Response3}, Context4} = cloudi:send_sync(Context3, ServiceNamePost, RequestInfo3, Request3, Timeout, Priority), true = ETag2 /= ETag3, true = LastModified2 =< LastModified3, RequestInfo4 = [{<<"range">>, <<"bytes=" "22-22">>}], Request4 = <<"ed">>, Response4 = <<"The quick red fox jumped over the lazy dog">>, {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag4}, {<<"last-modified">>, LastModified4}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], Response4}, Context5} = cloudi:send_sync(Context4, ServiceNamePost, RequestInfo4, Request4, Timeout, Priority), true = ETag3 /= ETag4, true = LastModified3 =< LastModified4, RequestInfo5 = [{<<"range">>, <<"bytes=" "42-42">>}], Request5 = <<"s.">>, Response5 = <<"The quick red fox jumped over the lazy dogs.">>, {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag5}, {<<"last-modified">>, LastModified5}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], Response5}, Context6} = cloudi:send_sync(Context5, ServiceNamePost, RequestInfo5, Request5, Timeout, Priority), true = ETag4 /= ETag5, true = LastModified4 =< LastModified5, RequestInfo6 = [{<<"range">>, <<"bytes=" "45-44">>}], {{ok, [{<<"status">>, <<"416">>}, {<<"content-range">>, <<"bytes */44">>}, {<<"accept-ranges">>, <<"bytes">>}], <<>>}, Context7} = cloudi:send_sync(Context6, ServiceNamePost, RequestInfo6, <<" Ignore this data!">>, Timeout, Priority), RequestInfo7 = [{<<"range">>, <<"bytes=" "44-44">>}], Request7 = <<" The fox later became a Hollywood actor.">>, Response7 = <<"The quick red fox jumped over the lazy dogs.", Request7/binary>>, {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag7}, {<<"last-modified">>, LastModified7}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], Response7}, Context8} = cloudi:send_sync(Context7, ServiceNamePost, RequestInfo7, Request7, Timeout, Priority), true = ETag5 /= ETag7, true = LastModified5 =< LastModified7, Request8 = <<" The end.">>, Response8 = <>, {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag8}, {<<"last-modified">>, LastModified8}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], Response8}, _} = cloudi:send_sync(Context8, ServiceNamePost, <<>>, Request8, Timeout, Priority), true = ETag7 /= ETag8, true = LastModified7 =< LastModified8, {ok, Response8} = file:read_file(writable_filepath1(Config)), ok. t_filesystem_basic_read_cache_1(_Config) -> Context0 = cloudi:new(), ServiceNameGet = ?SERVICE_PREFIX1 ++ ?ASCII_FILE ++ "/get", ASCII = erlang:list_to_binary(lists:seq(0, 126)), Request = <<>>, Timeout = undefined, % default Priority = undefined, % default {{ok, [{<<"content-type">>, <<"application/octet-stream">>}, {<<"content-disposition">>, <<"attachment; filename=\"ASCII.bin\"">>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], ASCII}, Context1} = cloudi:send_sync(Context0, ServiceNameGet, <<>>, Request, Timeout, Priority), RequestInfo1 = [{<<"if-none-match">>, ETag}], {{ok, [{<<"status">>, <<"304">>}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], <<>>}, Context2} = cloudi:send_sync(Context1, ServiceNameGet, RequestInfo1, Request, Timeout, Priority), InvalidETag = <<"invalid-etag">>, RequestInfo2 = [{<<"if-none-match">>, InvalidETag}], {{ok, [{<<"content-type">>, <<"application/octet-stream">>}, {<<"content-disposition">>, <<"attachment; filename=\"ASCII.bin\"">>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], ASCII}, Context3} = cloudi:send_sync(Context2, ServiceNameGet, RequestInfo2, Request, Timeout, Priority), RequestInfo3 = [{<<"if-match">>, InvalidETag}], {{ok, [{<<"status">>, <<"412">>}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], <<>>}, Context4} = cloudi:send_sync(Context3, ServiceNameGet, RequestInfo3, Request, Timeout, Priority), RequestInfo4 = [{<<"if-match">>, ETag}], {{ok, [{<<"content-type">>, <<"application/octet-stream">>}, {<<"content-disposition">>, <<"attachment; filename=\"ASCII.bin\"">>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], ASCII}, Context5} = cloudi:send_sync(Context4, ServiceNameGet, RequestInfo4, Request, Timeout, Priority), RequestInfo5 = [{<<"if-modified-since">>, LastModified}], {{ok, [{<<"status">>, <<"304">>}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], <<>>}, Context6} = cloudi:send_sync(Context5, ServiceNameGet, RequestInfo5, Request, Timeout, Priority), OldDate = <<"Mon, 01 Jan 1900 00:00:00 GMT">>, RequestInfo6 = [{<<"if-modified-since">>, OldDate}], {{ok, [{<<"content-type">>, <<"application/octet-stream">>}, {<<"content-disposition">>, <<"attachment; filename=\"ASCII.bin\"">>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], ASCII}, Context7} = cloudi:send_sync(Context6, ServiceNameGet, RequestInfo6, Request, Timeout, Priority), RequestInfo7 = [{<<"if-unmodified-since">>, LastModified}], {{ok, [{<<"status">>, <<"412">>}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], <<>>}, Context8} = cloudi:send_sync(Context7, ServiceNameGet, RequestInfo7, Request, Timeout, Priority), RequestInfo8 = [{<<"if-unmodified-since">>, OldDate}], {{ok, [{<<"content-type">>, <<"application/octet-stream">>}, {<<"content-disposition">>, <<"attachment; filename=\"ASCII.bin\"">>}, {<<"cache-control">>, <<"public">>}, {<<"expires">>, _}, {<<"etag">>, ETag}, {<<"last-modified">>, LastModified}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], ASCII}, _} = cloudi:send_sync(Context8, ServiceNameGet, RequestInfo8, Request, Timeout, Priority), ok. t_filesystem_size_limit_1(Config) -> Context0 = cloudi:new(), ServiceNameGet = ?SERVICE_PREFIX1 ++ ?WRITABLE_FILENAME1 ++ "/get", ServiceNamePost = ?SERVICE_PREFIX1 ++ ?WRITABLE_FILENAME1 ++ "/post", Timeout = undefined, % default Priority = undefined, % default {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"etag">>, ETag0}, {<<"last-modified">>, LastModified0}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], <<>>}, Context1} = cloudi:send_sync(Context0, ServiceNameGet, <<>>, <<>>, Timeout, Priority), {error, enoent} = file:read_file(writable_filepath2(Config)), Request1 = <<0:8192>>, % 1 Kb {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"etag">>, ETag1}, {<<"last-modified">>, LastModified1}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], Request1}, Context2} = cloudi:send_sync(Context1, ServiceNamePost, <<>>, Request1, Timeout, Priority), {ok, Request1} = file:read_file(writable_filepath2(Config)), true = ETag0 /= ETag1, true = LastModified0 =< LastModified1, Request2 = <<1:8192>>, % 1 Kb Response2 = <>, {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"etag">>, ETag2}, {<<"last-modified">>, LastModified2}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], Response2}, Context3} = cloudi:send_sync(Context2, ServiceNamePost, <<>>, Request2, Timeout, Priority), true = ETag1 /= ETag2, true = LastModified1 =< LastModified2, {ok, Response2} = file:read_file(writable_filepath2(Config)), Request3 = <<2:8>>, % 1 byte {{ok, [{<<"status">>, <<"400">>}], <<>>}, _} = cloudi:send_sync(Context3, ServiceNamePost, <<>>, Request3, Timeout, Priority), ok. t_filesystem_size_limit_2(Config) -> Context0 = cloudi:new(), ServiceNameGet = ?SERVICE_PREFIX1 ++ ?WRITABLE_FILENAME1 ++ "/get", ServiceNamePut = ?SERVICE_PREFIX1 ++ ?WRITABLE_FILENAME1 ++ "/put", Timeout = undefined, % default Priority = undefined, % default {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"etag">>, ETag0}, {<<"last-modified">>, LastModified0}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], <<>>}, Context1} = cloudi:send_sync(Context0, ServiceNameGet, <<>>, <<>>, Timeout, Priority), {error, enoent} = file:read_file(writable_filepath2(Config)), Request1 = <<0:8192>>, % 1 Kb {{ok, [{<<"content-type">>, <<"text/plain">>}, {<<"content-disposition">>, <<"attachment; filename=\"" ?WRITABLE_FILENAME1 "\"">>}, {<<"etag">>, ETag1}, {<<"last-modified">>, LastModified1}, {<<"date">>, _}, {<<"accept-ranges">>, <<"bytes">>}], Request1}, Context2} = cloudi:send_sync(Context1, ServiceNamePut, <<>>, Request1, Timeout, Priority), {ok, Request1} = file:read_file(writable_filepath2(Config)), true = ETag0 /= ETag1, true = LastModified0 =< LastModified1, Request2 = <<0:8200>>, % 1 Kb + 1 byte {{ok, [{<<"status">>, <<"400">>}], <<>>}, _} = cloudi:send_sync(Context2, ServiceNamePut, <<>>, Request2, Timeout, Priority), ok. %%%------------------------------------------------------------------------ %%% Private functions %%%------------------------------------------------------------------------ writable_filepath1(Config) -> filename:join(?config(tmpdir1, Config), ?WRITABLE_FILENAME1). writable_filepath2(Config) -> filename:join(?config(tmpdir2, Config), ?WRITABLE_FILENAME1).