Additional test coverage

This commit is contained in:
Gavin M. Roy 2016-04-15 00:32:25 -04:00
parent b4aef6f3ea
commit 58365970b5
7 changed files with 350 additions and 432 deletions

View File

@ -5,5 +5,6 @@
{eunit_exclude_deps, true}.
{eunit_opts, [verbose, {skip_deps, true}]}.
{deps, [
{jsx, ".*", {git, "https://github.com/talentdeficit/jsx.git", {tag, "v2.8.0"}}}
{jsx, ".*", {git, "https://github.com/talentdeficit/jsx.git", {tag, "v2.8.0"}}},
{meck, ".*", {git, "https://github.com/eproxus/meck.git", {tag, "0.8.4"}}}
]}.

View File

@ -9,7 +9,8 @@
-behavior(gen_server).
%% API exports
-export([set_credentials/2]).
-export([get_credentials/0,
set_credentials/2]).
%% gen-server exports
-export([start_link/0,
@ -31,6 +32,11 @@
%% exported wrapper functions
%%====================================================================
-spec get_credentials() -> {ok, access_key(), secret_access_key()}.
get_credentials() ->
gen_server:call(httpc_aws, get_credentials).
-spec set_credentials(access_key(), secret_access_key()) -> ok.
%% @spec set_credentials(AccessKey, SecretAccessKey) -> ok
%% where
@ -79,6 +85,9 @@ handle_call({set_credentials, AccessKey, SecretAccessKey}, _, State) ->
{reply, ok, State#state{access_key = AccessKey,
secret_access_key = SecretAccessKey}};
handle_call(get_credentials, _, State) ->
{reply, {ok, State#state.access_key, State#state.secret_access_key}, State};
handle_call(_Request, _From, State) ->
{noreply, State}.

View File

@ -438,8 +438,6 @@ lookup_credentials(_, AccessKey, SecretKey) ->
%% @end
lookup_credentials_from_config(Profile, {error,_}, _) ->
lookup_credentials_from_file(Profile, credentials_file_data());
lookup_credentials_from_config(Profile, _, {error,_}) ->
lookup_credentials_from_file(Profile, credentials_file_data());
lookup_credentials_from_config(_, AccessKey, SecretKey) ->
{ok, AccessKey, SecretKey, undefined, undefined}.

View File

@ -14,7 +14,7 @@
-define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5, Type, [I]}).
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
init([]) ->
{ok, {{one_for_one, 5, 10}, [?CHILD(httpc_aws, worker)]}}.
{ok, {{one_for_one, 5, 10}, [?CHILD(httpc_aws, worker)]}}.

View File

@ -2,447 +2,317 @@
-include_lib("eunit/include/eunit.hrl").
%% Return the parsed configuration file data
config_file_data_test() ->
os:putenv("AWS_CONFIG_FILE",
filename:join([filename:absname("."), "test",
"test_aws_config.ini"])),
Expectation = [
{"default",
[{aws_access_key_id, "default-key"},
{aws_secret_access_key, "default-access-key"},
{region, "us-east-1"}]},
{"profile testing",
[{aws_access_key_id, "foo1"},
{aws_secret_access_key, "bar2"},
{s3, [{max_concurrent_requests, 10},
{max_queue_size, 1000}]},
{region, "us-west-2"}]},
{"profile no-region",
[{aws_access_key_id, "foo2"},
{aws_secret_access_key, "bar3"}]},
{"profile only-key",
[{aws_access_key_id, "foo3"}]},
{"profile only-secret",
[{aws_secret_access_key, "foo4"}]},
{"profile bad-entry",
[{aws_secret_access, "foo5"}]}
],
?assertEqual(Expectation,
httpc_aws_config:config_file_data()).
%% Return the default configuration when the environment variable is set
config_file_test() ->
os:putenv("AWS_CONFIG_FILE", "/etc/aws/config"),
?assertEqual("/etc/aws/config",
httpc_aws_config:config_file()).
%% Return the default configuration path based upon the user's home directory
config_file_no_env_var_test() ->
os:unsetenv("AWS_CONFIG_FILE"),
os:putenv("HOME", "/home/gavinr"),
?assertEqual("/home/gavinr/.aws/config",
httpc_aws_config:config_file()).
-include("httpc_aws.hrl").
%% Return the parsed configuration file data
credentials_file_data_test() ->
os:putenv("AWS_SHARED_CREDENTIALS_FILE",
filename:join([filename:absname("."), "test",
"test_aws_credentials.ini"])),
Expectation = [
{"default",
[{aws_access_key_id, "foo1"},
{aws_secret_access_key, "bar1"}]},
{"development",
[{aws_access_key_id, "foo2"},
{aws_secret_access_key, "bar2"}]},
{"only-key",
[{aws_access_key_id, "foo3"}]},
{"only-secret",
[{aws_secret_access_key, "foo4"}]},
{"bad-entry",
[{aws_secret_access, "foo5"}]}
],
?assertEqual(Expectation,
httpc_aws_config:credentials_file_data()).
config_file_test_() ->
[
{"from environment variable", fun() ->
os:putenv("AWS_CONFIG_FILE", "/etc/aws/config"),
?assertEqual("/etc/aws/config", httpc_aws_config:config_file())
end},
{"default without environment variable", fun() ->
os:unsetenv("AWS_CONFIG_FILE"),
os:putenv("HOME", "/home/gavinr"),
?assertEqual("/home/gavinr/.aws/config",
httpc_aws_config:config_file())
end}
].
%% Return the default configuration when the environment variable is set
credentials_file_test() ->
os:putenv("AWS_SHARED_CREDENTIALS_FILE", "/etc/aws/credentials"),
?assertEqual("/etc/aws/credentials",
httpc_aws_config:credentials_file()).
%% Return the default configuration path based upon the user's home directory
credentials_no_env_var_test() ->
os:unsetenv("AWS_SHARED_CREDENTIALS_FILE"),
os:putenv("HOME", "/home/gavinr"),
?assertEqual("/home/gavinr/.aws/credentials",
httpc_aws_config:credentials_file()).
config_file_data_test_() ->
[
{"successfully parses ini", fun() ->
setup_test_config_env_var(),
Expectation = [
{"default",
[{aws_access_key_id, "default-key"},
{aws_secret_access_key, "default-access-key"},
{region, "us-east-1"}]},
{"profile testing",
[{aws_access_key_id, "foo1"},
{aws_secret_access_key, "bar2"},
{s3, [{max_concurrent_requests, 10},
{max_queue_size, 1000}]},
{region, "us-west-2"}]},
{"profile no-region",
[{aws_access_key_id, "foo2"},
{aws_secret_access_key, "bar3"}]},
{"profile only-key",
[{aws_access_key_id, "foo3"}]},
{"profile only-secret",
[{aws_secret_access_key, "foo4"}]},
{"profile bad-entry",
[{aws_secret_access, "foo5"}]}
],
?assertEqual(Expectation,
httpc_aws_config:config_file_data())
end},
{"file does not exist", fun() ->
?assertEqual({error, enoent},
httpc_aws_config:ini_file_data(filename:join([filename:absname("."), "bad_path"]), false))
end
},
{"file exists but path is invalid", fun() ->
?assertEqual({error, enoent},
httpc_aws_config:ini_file_data(filename:join([filename:absname("."), "bad_path"]), true))
end
}
].
%% Return the home directory path based upon the HOME shell environment variable
home_path_test() ->
os:putenv("HOME", "/home/gavinr"),
?assertEqual("/home/gavinr",
httpc_aws_config:home_path()).
%% Test that the cwd is returned if HOME is not set in the shell environment
home_path_no_env_var_test() ->
os:unsetenv("HOME"),
?assertEqual(filename:absname("."),
httpc_aws_config:home_path()).
credentials_file_test_() ->
[
{"from environment variable", fun() ->
os:putenv("AWS_SHARED_CREDENTIALS_FILE", "/etc/aws/credentials"),
?assertEqual("/etc/aws/credentials", httpc_aws_config:credentials_file())
end},
{"default without environment variable", fun() ->
os:unsetenv("AWS_SHARED_CREDENTIALS_FILE"),
os:putenv("HOME", "/home/gavinr"),
?assertEqual("/home/gavinr/.aws/credentials",
httpc_aws_config:credentials_file())
end}
].
%% Test that an atom is returned when passing in a list
ini_format_key_when_list_test() ->
?assertEqual(test_key, httpc_aws_config:ini_format_key("test_key")).
credentials_test_() ->
{
foreach,
fun () ->
meck:new(httpc),
reset_environment(),
[httpc]
end,
fun meck:unload/1,
[
{"from environment variables", fun() ->
os:putenv("AWS_ACCESS_KEY_ID", "Sésame"),
os:putenv("AWS_SECRET_ACCESS_KEY", "ouvre-toi"),
?assertEqual({ok, "Sésame", "ouvre-toi", undefined, undefined},
httpc_aws_config:credentials())
end},
{"from config file with default profile", fun() ->
setup_test_config_env_var(),
?assertEqual({ok, "default-key", "default-access-key", undefined, undefined},
httpc_aws_config:credentials())
end},
{"with missing environment variable", fun() ->
os:putenv("AWS_ACCESS_KEY_ID", "Sésame"),
?assertEqual({error, undefined},
httpc_aws_config:credentials())
end},
{"from config file with default profile", fun() ->
setup_test_config_env_var(),
?assertEqual({ok, "default-key", "default-access-key", undefined, undefined},
httpc_aws_config:credentials())
end},
{"from config file with profile", fun() ->
setup_test_config_env_var(),
?assertEqual({ok, "foo1", "bar2", undefined, undefined},
httpc_aws_config:credentials("testing"))
end},
{"from config file with bad profile", fun() ->
setup_test_config_env_var(),
?assertEqual({error, undefined},
httpc_aws_config:credentials("bad-profile-name"))
end},
{"from credentials file with default profile", fun() ->
setup_test_credentials_env_var(),
?assertEqual({ok, "foo1", "bar1", undefined, undefined},
httpc_aws_config:credentials())
end},
{"from credentials file with profile", fun() ->
setup_test_credentials_env_var(),
?assertEqual({ok, "foo2", "bar2", undefined, undefined},
httpc_aws_config:credentials("development"))
end},
{"from credentials file with bad profile", fun() ->
setup_test_credentials_env_var(),
?assertEqual({error, undefined},
httpc_aws_config:credentials("bad-profile-name"))
end},
{"from credentials file with only the key in profile", fun() ->
setup_test_credentials_env_var(),
?assertEqual({error, undefined},
httpc_aws_config:credentials("only-key"))
end},
{"from credentials file with only the value in profile", fun() ->
setup_test_credentials_env_var(),
?assertEqual({error, undefined},
httpc_aws_config:credentials("only-value"))
end},
{"from credentials file with missing keys in profile", fun() ->
setup_test_credentials_env_var(),
?assertEqual({error, undefined},
httpc_aws_config:credentials("bad-entry"))
end},
{"from instance metadata service", fun() ->
CredsBody = "{\n \"Code\" : \"Success\",\n \"LastUpdated\" : \"2016-03-31T21:51:49Z\",\n \"Type\" : \"AWS-HMAC\",\n \"AccessKeyId\" : \"ASIAIMAFAKEACCESSKEY\",\n \"SecretAccessKey\" : \"2+t64tZZVaz0yp0x1G23ZRYn+FAKEyVALUEs/4qh\",\n \"Token\" : \"FAKE//////////wEAK/TOKEN/VALUE=\",\n \"Expiration\" : \"2016-04-01T04:13:28Z\"\n}",
meck:sequence(httpc, request, 4,
[{ok, {{protocol, 200, message}, headers, "Bob"}},
{ok, {{protocol, 200, message}, headers, CredsBody}}]),
Expectation = {ok, "ASIAIMAFAKEACCESSKEY", "2+t64tZZVaz0yp0x1G23ZRYn+FAKEyVALUEs/4qh", "2016-04-01T04:13:28Z", "FAKE//////////wEAK/TOKEN/VALUE="},
?assertEqual(Expectation, httpc_aws_config:credentials())
end
},
{"with instance metadata service role error", fun() ->
meck:expect(httpc, request, 4, {error, timeout}),
?assertEqual({error, undefined}, httpc_aws_config:credentials())
end
},
{"with instance metadata service role http error", fun() ->
meck:expect(httpc, request, 4,
{ok, {{protocol, 500, message}, headers, "Internal Server Error"}}),
?assertEqual({error, undefined}, httpc_aws_config:credentials())
end
},
{"with instance metadata service credentials error", fun() ->
meck:sequence(httpc, request, 4,
[{ok, {{protocol, 200, message}, headers, "Bob"}},
{error, timeout}]),
?assertEqual({error, undefined}, httpc_aws_config:credentials())
end
},
{"with instance metadata service credentials not found", fun() ->
meck:sequence(httpc, request, 4,
[{ok, {{protocol, 200, message}, headers, "Bob"}},
{ok, {{protocol, 404, message}, headers, "File Not Found"}}]),
?assertEqual({error, undefined}, httpc_aws_config:credentials())
end
}
%% Test that an error is returned when passing in a binary
ini_format_key_when_binary_test() ->
?assertEqual({error, type}, httpc_aws_config:ini_format_key(<<"test_key">>)).
%% Test that a string value with an integer returns the proper value
maybe_convert_number_test() ->
?assertEqual(123, httpc_aws_config:maybe_convert_number("123")).
%% Test that a string value with an float returns the proper value
maybe_convert_number_float_test() ->
?assertEqual(123.456, httpc_aws_config:maybe_convert_number("123.456")).
%% Test that a string value with an float returns the proper value
maybe_convert_number_no_number_test() ->
?assertEqual("hello, world", httpc_aws_config:maybe_convert_number("hello, world")).
%% Test that the appropriate error is raised when the specified path does not exist and the file is not found
ini_file_data_file_doesnt_exist_test() ->
?assertEqual({error, enoent}, httpc_aws_config:ini_file_data(filename:join([filename:absname("."), "bad_path"]), false)).
%% Test that the appropriate error is raised when the specified path does not exist and the file is found
ini_file_data_bad_path_test() ->
?assertEqual({error, enoent}, httpc_aws_config:ini_file_data(filename:join([filename:absname("."), "bad_path"]), true)).
%% Test that the appropriate error is raised when trying to read a file that doesn't exist
read_file_bad_path_test() ->
?assertEqual({error, enoent}, httpc_aws_config:read_file(filename:join([filename:absname("."), "bad_path"]))).
%% Test that the appropriate error is raised when trying to read a file that errors out when reading the line
read_file_bad_handle_test() ->
{MegaSecs, Secs, MicroSecs} = now(),
Name = lists:flatten(io_lib:format("~p-~p-~p.tmp", [MegaSecs, Secs, MicroSecs])),
{ok, Handle} = file:open(Name, [write]),
file:close(Handle),
?assertEqual({error,terminated}, httpc_aws_config:read_file(Handle, [])),
file:delete(Name).
%% Test the profile value set in an environment variable is returned
profile_from_env_var_test() ->
os:putenv("AWS_DEFAULT_PROFILE", "httpc-aws test"),
?assertEqual("httpc-aws test",
httpc_aws_config:profile()).
%% Test the default profile value is returned when no environment variable is set
profile_no_env_var_test() ->
os:unsetenv("AWS_DEFAULT_PROFILE"),
?assertEqual("default",
httpc_aws_config:profile()).
%% Test that the proper config section is returned for the default profile
values_with_default_profile_test() ->
os:putenv("AWS_CONFIG_FILE",
filename:join([filename:absname("."), "test",
"test_aws_config.ini"])),
Expectation = [{aws_access_key_id, "default-key"},
{aws_secret_access_key, "default-access-key"},
{region, "us-east-1"}],
?assertEqual(Expectation, httpc_aws_config:values("default")).
]}.
%% Test that the proper config section is returned for the unprefixed testing profile
values_with_unprefixed_testing_profile_test() ->
os:putenv("AWS_CONFIG_FILE",
filename:join([filename:absname("."), "test",
"test_aws_config.ini"])),
Expectation = [{aws_access_key_id, "foo1"},
{aws_secret_access_key, "bar2"},
{s3, [{max_concurrent_requests, 10},
{max_queue_size, 1000}]},
{region, "us-west-2"}],
?assertEqual(Expectation, httpc_aws_config:values("testing")).
home_path_test_() ->
[
{"with HOME", fun() ->
os:putenv("HOME", "/home/gavinr"),
?assertEqual("/home/gavinr",
httpc_aws_config:home_path())
end},
{"without HOME", fun() ->
os:unsetenv("HOME"),
?assertEqual(filename:absname("."),
httpc_aws_config:home_path())
end}
].
%% Test that an error is returned
config_data_with_no_config_file_test() ->
os:unsetenv("AWS_CONFIG_FILE"),
?assertEqual({error, enoent}, httpc_aws_config:values("testing")).
%% Test that the correct region is returned from an environment variable
region_with_env_var_test() ->
os:putenv("AWS_DEFAULT_REGION", "us-west-1"),
?assertEqual({ok, "us-west-1"}, httpc_aws_config:region()).
ini_format_key_test_() ->
[
{"when value is list", fun() ->
?assertEqual(test_key, httpc_aws_config:ini_format_key("test_key"))
end},
{"when value is binary", fun() ->
?assertEqual({error, type}, httpc_aws_config:ini_format_key(<<"test_key">>))
end}
].
%% Test that the correct region is returned from the config file for the default profile
region_with_config_file_and_default_profile_test() ->
maybe_convert_number_test_() ->
[
{"when string contains an integer", fun() ->
?assertEqual(123, httpc_aws_config:maybe_convert_number("123"))
end},
{"when string contains a float", fun() ->
?assertEqual(123.456, httpc_aws_config:maybe_convert_number("123.456"))
end},
{"when string does not contain a number", fun() ->
?assertEqual("hello, world", httpc_aws_config:maybe_convert_number("hello, world"))
end}
].
profile_test_() ->
[
{"from environment variable", fun() ->
os:putenv("AWS_DEFAULT_PROFILE", "httpc-aws test"),
?assertEqual("httpc-aws test", httpc_aws_config:profile())
end},
{"default without environment variable", fun() ->
os:unsetenv("AWS_DEFAULT_PROFILE"),
?assertEqual("default", httpc_aws_config:profile())
end}
].
read_file_test_() ->
[
{"file does not exist", fun() ->
?assertEqual({error, enoent}, httpc_aws_config:read_file(filename:join([filename:absname("."), "bad_path"])))
end},
{"file handle is closed", fun() ->
{MegaSecs, Secs, MicroSecs} = now(),
Name = lists:flatten(io_lib:format("~p-~p-~p.tmp", [MegaSecs, Secs, MicroSecs])),
{ok, Handle} = file:open(Name, [write]),
file:close(Handle),
?assertEqual({error,terminated}, httpc_aws_config:read_file(Handle, [])),
file:delete(Name)
end}
].
region_test_() ->
{
foreach,
fun () ->
meck:new(httpc),
reset_environment(),
[httpc]
end,
fun meck:unload/1,
[
{"with environment variable", fun() ->
os:putenv("AWS_DEFAULT_REGION", "us-west-1"),
?assertEqual({ok, "us-west-1"}, httpc_aws_config:region())
end},
{"with config file and specified profile", fun() ->
setup_test_config_env_var(),
?assertEqual({ok, "us-west-2"}, httpc_aws_config:region("testing"))
end},
{"with config file using default profile", fun() ->
setup_test_config_env_var(),
?assertEqual({ok, "us-east-1"}, httpc_aws_config:region())
end},
{"missing profile in config", fun() ->
setup_test_config_env_var(),
?assertEqual({error, undefined}, httpc_aws_config:region("no-region"))
end},
{"from instance metadata service", fun() ->
meck:expect(httpc, request, 4,
{ok, {{protocol, 200, message}, headers, "us-west-1a"}}),
?assertEqual({ok, "us-west-1"}, httpc_aws_config:region())
end},
{"full lookup failure", fun() ->
?assertEqual({error, undefined}, httpc_aws_config:region())
end},
{"http error failure", fun() ->
meck:expect(httpc, request, 4,
{ok, {{protocol, 500, message}, headers, "Internal Server Error"}}),
?assertEqual({error, undefined}, httpc_aws_config:region())
end}
]}.
reset_environment() ->
os:unsetenv("AWS_ACCESS_KEY_ID"),
os:unsetenv("AWS_DEFAULT_REGION"),
os:putenv("AWS_CONFIG_FILE",
filename:join([filename:absname("."), "test",
"test_aws_config.ini"])),
?assertEqual({ok, "us-east-1"}, httpc_aws_config:region()).
%% Test that the correct region is returned from the config file for the specified profile
region_with_config_file_test() ->
os:unsetenv("AWS_DEFAULT_REGION"),
os:putenv("AWS_CONFIG_FILE",
filename:join([filename:absname("."), "test",
"test_aws_config.ini"])),
?assertEqual({ok, "us-west-2"}, httpc_aws_config:region("testing")).
%% Test that an error is returned when there is no config file, region, or EC2 instance metadata service
region_without_config_file_test() ->
os:unsetenv("AWS_DEFAULT_REGION"),
os:unsetenv("AWS_CONFIG_FILE"),
?assertEqual({error, undefined}, httpc_aws_config:region()).
%% Test that an error is returned when the config for the specified profile doesnt have a region
region_with_profile_without_region_test() ->
os:unsetenv("AWS_DEFAULT_REGION"),
os:putenv("AWS_CONFIG_FILE",
filename:join([filename:absname("."), "test",
"test_aws_config.ini"])),
?assertEqual({error, undefined}, httpc_aws_config:region("no-region")).
%% Test stripping the az designation from the region
region_from_availability_zone_test() ->
?assertEqual("us-east-1", httpc_aws_config:region_from_availability_zone("us-east-1a")).
%% Test that the availability-zone URL is constructed correctly
instance_availability_zone_url_test() ->
?assertEqual("http://169.254.169.254/latest/meta-data/placement/availability-zone",
httpc_aws_config:instance_availability_zone_url()).
%% Test the return an individual value from the AWS config file for the specified profile
value_found_test() ->
os:putenv("AWS_CONFIG_FILE",
filename:join([filename:absname("."), "test",
"test_aws_config.ini"])),
?assertEqual("default-key",
httpc_aws_config:value("default", aws_access_key_id)).
%% Test the error return an unset value from the AWS config file for the specified profile
value_not_set_test() ->
os:putenv("AWS_CONFIG_FILE",
filename:join([filename:absname("."), "test",
"test_aws_config.ini"])),
?assertEqual({error, undefined},
httpc_aws_config:value("default", bad_key_name)).
%% Test the error return when the config file is not valid
value_no_config_file_test() ->
os:putenv("AWS_CONFIG_FILE",
filename:join([filename:absname("."), "test",
"invalid-test-data.ini"])),
?assertEqual({error, enoent},
httpc_aws_config:value("default", bad_key_name)).
%% Test values when a requested profile is not configured
values_unset_profile_test() ->
os:putenv("AWS_CONFIG_FILE",
filename:join([filename:absname("."), "test",
"test_aws_config.ini"])),
?assertEqual({error, undefined},
httpc_aws_config:values("invalid-profile")).
%% Test credential values from environment variables
credentials_env_var_test() ->
os:putenv("AWS_ACCESS_KEY_ID", "Sésame"),
os:putenv("AWS_SECRET_ACCESS_KEY", "ouvre-toi"),
os:unsetenv("AWS_CONFIG_FILE"),
os:unsetenv("AWS_SHARED_CREDENTIALS_FILE"),
Expectation = {ok, "Sésame", "ouvre-toi", undefined, undefined},
?assertEqual(Expectation, httpc_aws_config:credentials()).
%% Test credential values from default profile in config
credentials_config_file_test() ->
os:unsetenv("AWS_ACCESS_KEY_ID"),
os:unsetenv("AWS_SECRET_ACCESS_KEY"),
os:putenv("AWS_CONFIG_FILE",
setup_test_file_with_env_var("AWS_CONFIG_FILE", "bad_config.ini"),
setup_test_file_with_env_var("AWS_SHARED_CREDENTIALS_FILE",
"bad_credentials.ini"),
meck:expect(httpc, request, 4, {error, timeout}).
setup_test_config_env_var() ->
setup_test_file_with_env_var("AWS_CONFIG_FILE", "test_aws_config.ini").
setup_test_file_with_env_var(EnvVar, Filename) ->
os:putenv(EnvVar,
filename:join([filename:absname("."), "test",
"test_aws_config.ini"])),
os:unsetenv("AWS_SHARED_CREDENTIALS_FILE"),
Expectation = {ok, "default-key", "default-access-key", undefined, undefined},
?assertEqual(Expectation, httpc_aws_config:credentials()).
Filename])).
%% Test credential values from environment variables
credentials_partial_env_var_access_key_test() ->
os:putenv("AWS_ACCESS_KEY_ID", "Sésame"),
os:unsetenv("AWS_SECRET_ACCESS_KEY"),
os:unsetenv("AWS_CONFIG_FILE"),
os:unsetenv("AWS_SHARED_CREDENTIALS_FILE"),
Expectation = {error, undefined},
?assertEqual(Expectation, httpc_aws_config:credentials()).
%% Test credential values from environment variables
credentials_partial_env_var_secret_key_test() ->
os:unsetenv("AWS_ACCESS_KEY_ID"),
os:putenv("AWS_SECRET_ACCESS_KEY", "ouvre-toi"),
os:unsetenv("AWS_CONFIG_FILE"),
os:unsetenv("AWS_SHARED_CREDENTIALS_FILE"),
Expectation = {error, undefined},
?assertEqual(Expectation, httpc_aws_config:credentials()).
%% Test credential values from default profile in config with credentials file
credentials_config_file_with_credentials_file_test() ->
os:unsetenv("AWS_ACCESS_KEY_ID"),
os:unsetenv("AWS_SECRET_ACCESS_KEY"),
os:putenv("AWS_CONFIG_FILE",
filename:join([filename:absname("."), "test",
"test_aws_config.ini"])),
os:putenv("AWS_SHARED_CREDENTIALS_FILE",
filename:join([filename:absname("."), "test",
"test_aws_credentials.ini"])),
Expectation = {ok, "default-key", "default-access-key", undefined, undefined},
?assertEqual(Expectation, httpc_aws_config:credentials()).
%% Test credential values when they cant be resolved
credentials_config_file_only_with_key_test() ->
os:unsetenv("AWS_ACCESS_KEY_ID"),
os:unsetenv("AWS_SECRET_ACCESS_KEY"),
os:putenv("AWS_CONFIG_FILE",
filename:join([filename:absname("."), "test",
"test_aws_config.ini"])),
os:unsetenv("AWS_SHARED_CREDENTIALS_FILE"),
Expectation = {error, undefined},
?assertEqual(Expectation, httpc_aws_config:credentials("only-key")).
%% Test credential values when they cant be resolved
credentials_config_file_only_with_secret_test() ->
os:unsetenv("AWS_ACCESS_KEY_ID"),
os:unsetenv("AWS_SECRET_ACCESS_KEY"),
os:putenv("AWS_CONFIG_FILE",
filename:join([filename:absname("."), "test",
"test_aws_config.ini"])),
os:unsetenv("AWS_SHARED_CREDENTIALS_FILE"),
Expectation = {error, undefined},
?assertEqual(Expectation, httpc_aws_config:credentials("only-secret")).
%% Test credential values when they cant be resolved
credentials_config_file_only_with_bad_profile_test() ->
os:unsetenv("AWS_ACCESS_KEY_ID"),
os:unsetenv("AWS_SECRET_ACCESS_KEY"),
os:putenv("AWS_CONFIG_FILE",
filename:join([filename:absname("."), "test",
"test_aws_config.ini"])),
os:unsetenv("AWS_SHARED_CREDENTIALS_FILE"),
Expectation = {error, undefined},
?assertEqual(Expectation, httpc_aws_config:credentials("bad-profile!")).
%% Test credential values when they cant be resolved
credentials_config_file_only_with_bad_entry_test() ->
os:unsetenv("AWS_ACCESS_KEY_ID"),
os:unsetenv("AWS_SECRET_ACCESS_KEY"),
os:putenv("AWS_CONFIG_FILE",
filename:join([filename:absname("."), "test",
"test_aws_config.ini"])),
os:unsetenv("AWS_SHARED_CREDENTIALS_FILE"),
Expectation = {error, undefined},
?assertEqual(Expectation, httpc_aws_config:credentials("bad-entry")).
%% Test credential values from default profile in config with credentials file
credentials_credentials_file_with_config_file_test() ->
os:unsetenv("AWS_ACCESS_KEY_ID"),
os:unsetenv("AWS_SECRET_ACCESS_KEY"),
os:putenv("AWS_CONFIG_FILE",
filename:join([filename:absname("."), "test",
"test_aws_config.ini"])),
os:putenv("AWS_SHARED_CREDENTIALS_FILE",
filename:join([filename:absname("."), "test",
"test_aws_credentials.ini"])),
Expectation = {ok, "foo2", "bar2", undefined, undefined},
?assertEqual(Expectation, httpc_aws_config:credentials("development")).
%% Test credential values from default profile in config with credentials file
credentials_credentials_file_without_config_file_test() ->
os:unsetenv("AWS_ACCESS_KEY_ID"),
os:unsetenv("AWS_SECRET_ACCESS_KEY"),
os:unsetenv("AWS_CONFIG_FILE"),
os:putenv("AWS_SHARED_CREDENTIALS_FILE",
filename:join([filename:absname("."), "test",
"test_aws_credentials.ini"])),
Expectation = {ok, "foo1", "bar1", undefined, undefined},
?assertEqual(Expectation, httpc_aws_config:credentials()).
%% Test credential values when they cant be resolved
credentials_credentials_file_only_with_key_test() ->
os:unsetenv("AWS_ACCESS_KEY_ID"),
os:unsetenv("AWS_SECRET_ACCESS_KEY"),
os:unsetenv("AWS_CONFIG_FILE"),
os:putenv("AWS_SHARED_CREDENTIALS_FILE",
filename:join([filename:absname("."), "test",
"test_aws_credentials.ini"])),
Expectation = {error, undefined},
?assertEqual(Expectation, httpc_aws_config:credentials("only-key")).
%% Test credential values when they cant be resolved
credentials_credentials_file_only_with_secret_test() ->
os:unsetenv("AWS_ACCESS_KEY_ID"),
os:unsetenv("AWS_SECRET_ACCESS_KEY"),
os:unsetenv("AWS_CONFIG_FILE"),
os:putenv("AWS_SHARED_CREDENTIALS_FILE",
filename:join([filename:absname("."), "test",
"test_aws_credentials.ini"])),
Expectation = {error, undefined},
?assertEqual(Expectation, httpc_aws_config:credentials("only-secret")).
%% Test credential values when they cant be resolved
credentials_credentials_file_only_with_bad_profile_test() ->
os:unsetenv("AWS_ACCESS_KEY_ID"),
os:unsetenv("AWS_SECRET_ACCESS_KEY"),
os:unsetenv("AWS_CONFIG_FILE"),
os:putenv("AWS_SHARED_CREDENTIALS_FILE",
filename:join([filename:absname("."), "test",
"test_aws_credentials.ini"])),
Expectation = {error, undefined},
?assertEqual(Expectation, httpc_aws_config:credentials("bad-profile!")).
%% Test credential values when they cant be resolved
credentials_credentials_file_only_with_bad_entry_test() ->
os:unsetenv("AWS_ACCESS_KEY_ID"),
os:unsetenv("AWS_SECRET_ACCESS_KEY"),
os:unsetenv("AWS_CONFIG_FILE"),
os:putenv("AWS_SHARED_CREDENTIALS_FILE",
filename:join([filename:absname("."), "test",
"test_aws_credentials.ini"])),
Expectation = {error, undefined},
?assertEqual(Expectation, httpc_aws_config:credentials("bad-entry")).
%% Test credential values when they cant be resolved
credentials_unresolved_test() ->
os:unsetenv("AWS_ACCESS_KEY_ID"),
os:unsetenv("AWS_SECRET_ACCESS_KEY"),
os:unsetenv("AWS_CONFIG_FILE"),
os:unsetenv("AWS_SHARED_CREDENTIALS_FILE"),
Expectation = {error, undefined},
?assertEqual(Expectation, httpc_aws_config:credentials()).
%% Test that the credentials URL is constructed correctly
instance_credentials_url_test() ->
?assertEqual("http://169.254.169.254/latest/meta-data/iam/security-credentials/bob",
httpc_aws_config:instance_credentials_url("bob")).
%% Test that the role URL is constructed correctly
instance_role_url_test() ->
?assertEqual("http://169.254.169.254/latest/meta-data/iam/security-credentials",
httpc_aws_config:instance_role_url()).
parse_credentials_response_ok_test() ->
Value = "{\n \"Code\" : \"Success\",\n \"LastUpdated\" : \"2016-03-31T21:51:49Z\",\n \"Type\" : \"AWS-HMAC\",\n \"AccessKeyId\" : \"ASIAIMAFAKEACCESSKEY\",\n \"SecretAccessKey\" : \"2+t64tZZVaz0yp0x1G23ZRYn+FAKEyVALUEs/4qh\",\n \"Token\" : \"FAKE//////////wEAK/TOKEN/VALUE=\",\n \"Expiration\" : \"2016-04-01T04:13:28Z\"\n}",
Expectation = {ok, "ASIAIMAFAKEACCESSKEY", "2+t64tZZVaz0yp0x1G23ZRYn+FAKEyVALUEs/4qh", "2016-04-01T04:13:28Z", "FAKE//////////wEAK/TOKEN/VALUE="},
?assertEqual(Expectation, httpc_aws_config:parse_credentials_response({ok, {{protocol, 200, message}, headers, Value}})).
parse_credentials_404_error_test() ->
Expectation = {error, undefined},
?assertEqual(Expectation, httpc_aws_config:parse_credentials_response({ok, {{protocol, 404, message}, headers, body}})).
parse_credentials_response_error_test() ->
Expectation = {error, undefined},
?assertEqual(Expectation, httpc_aws_config:parse_credentials_response({error, bad_request})).
setup_test_credentials_env_var() ->
setup_test_file_with_env_var("AWS_SHARED_CREDENTIALS_FILE",
"test_aws_credentials.ini").

View File

@ -0,0 +1,10 @@
-module(httpc_aws_sup_tests).
-include_lib("eunit/include/eunit.hrl").
init_test() ->
?assertEqual({ok, {{one_for_one, 5, 10},
[{httpc_aws, {httpc_aws, start_link, []},
permanent, 5, worker, [httpc_aws]}]}},
httpc_aws_sup:init([])).

View File

@ -0,0 +1,30 @@
-module(httpc_aws_tests).
-include_lib("eunit/include/eunit.hrl").
-include("httpc_aws.hrl").
api_test_() ->
{
foreach,
fun setup/0,
fun cleanup/1,
[
{"set_credentials values assigned",
fun() ->
AccessKey = "foo",
SecretKey = "bar",
ok = httpc_aws:set_credentials(AccessKey, SecretKey),
?assertEqual({ok, AccessKey, SecretKey},
httpc_aws:get_credentials())
end
}
]
}.
setup() ->
{ok, _Pid} = httpc_aws:start_link(),
httpc_aws.
cleanup(Name) ->
gen_server:stop(Name).