diff options
Diffstat (limited to 'lib')
46 files changed, 1635 insertions, 1550 deletions
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index d1f620d892..74cdecdec6 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -378,86 +378,96 @@ struct hmac_context static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context*); struct digest_type_t { - const char* type_str; - const EVP_MD* (*md_func)(void); /* NULL if notsup */ - ERL_NIF_TERM type_atom; + union { + const char* str; /* before init, NULL for end-of-table */ + ERL_NIF_TERM atom; /* after init, 'false' for end-of-table */ + }type; + union { + const EVP_MD* (*funcp)(void); /* before init, NULL if notsup */ + const EVP_MD* p; /* after init, NULL if notsup */ + }md; }; struct digest_type_t digest_types[] = { - {"md4", &EVP_md4}, - {"md5", &EVP_md5}, - {"ripemd160", &EVP_ripemd160}, - {"sha", &EVP_sha1}, - {"sha224", + {{"md4"}, {&EVP_md4}}, + {{"md5"}, {&EVP_md5}}, + {{"ripemd160"}, {&EVP_ripemd160}}, + {{"sha"}, {&EVP_sha1}}, + {{"sha224"}, #ifdef HAVE_SHA224 - &EVP_sha224 + {&EVP_sha224} #else - NULL + {NULL} #endif }, - {"sha256", + {{"sha256"}, #ifdef HAVE_SHA256 - &EVP_sha256 + {&EVP_sha256} #else - NULL + {NULL} #endif }, - {"sha384", + {{"sha384"}, #ifdef HAVE_SHA384 - &EVP_sha384 + {&EVP_sha384} #else - NULL + {NULL} #endif }, - {"sha512", + {{"sha512"}, #ifdef HAVE_SHA512 - &EVP_sha512 + {&EVP_sha512} #else - NULL + {NULL} #endif }, - {NULL} + {{NULL}} }; static struct digest_type_t* get_digest_type(ERL_NIF_TERM type); struct cipher_type_t { - const char* type_str; - const EVP_CIPHER* (*cipher_func)(void); /* NULL if notsup */ + union { + const char* str; /* before init */ + ERL_NIF_TERM atom; /* after init */ + }type; + union { + const EVP_CIPHER* (*funcp)(void); /* before init, NULL if notsup */ + const EVP_CIPHER* p; /* after init, NULL if notsup */ + }cipher; const size_t key_len; /* != 0 to also match on key_len */ - ERL_NIF_TERM type_atom; }; struct cipher_type_t cipher_types[] = { - {"rc2_cbc", &EVP_rc2_cbc}, - {"des_cbc", &EVP_des_cbc}, - {"des_cfb", &EVP_des_cfb8}, - {"des_ecb", &EVP_des_ecb}, - {"des_ede3_cbc", &EVP_des_ede3_cbc}, - {"des_ede3_cbf", + {{"rc2_cbc"}, {&EVP_rc2_cbc}}, + {{"des_cbc"}, {&EVP_des_cbc}}, + {{"des_cfb"}, {&EVP_des_cfb8}}, + {{"des_ecb"}, {&EVP_des_ecb}}, + {{"des_ede3_cbc"}, {&EVP_des_ede3_cbc}}, + {{"des_ede3_cbf"}, #ifdef HAVE_DES_ede3_cfb_encrypt - &EVP_des_ede3_cfb8 + {&EVP_des_ede3_cfb8} #else - NULL + {NULL} #endif }, - {"blowfish_cbc", &EVP_bf_cbc}, - {"blowfish_cfb64", &EVP_bf_cfb64}, - {"blowfish_ofb64", &EVP_bf_ofb}, - {"blowfish_ecb", &EVP_bf_ecb}, - {"aes_cbc", &EVP_aes_128_cbc, 16}, - {"aes_cbc", &EVP_aes_192_cbc, 24}, - {"aes_cbc", &EVP_aes_256_cbc, 32}, - {"aes_cbc128", &EVP_aes_128_cbc}, - {"aes_cbc256", &EVP_aes_256_cbc}, - {"aes_cfb8", &EVP_aes_128_cfb8}, - {"aes_cfb128", &EVP_aes_128_cfb128}, - {"aes_ecb", &EVP_aes_128_ecb, 16}, - {"aes_ecb", &EVP_aes_192_ecb, 24}, - {"aes_ecb", &EVP_aes_256_ecb, 32}, - {NULL} + {{"blowfish_cbc"}, {&EVP_bf_cbc}}, + {{"blowfish_cfb64"}, {&EVP_bf_cfb64}}, + {{"blowfish_ofb64"}, {&EVP_bf_ofb}}, + {{"blowfish_ecb"}, {&EVP_bf_ecb}}, + {{"aes_cbc"}, {&EVP_aes_128_cbc}, 16}, + {{"aes_cbc"}, {&EVP_aes_192_cbc}, 24}, + {{"aes_cbc"}, {&EVP_aes_256_cbc}, 32}, + {{"aes_cbc128"}, {&EVP_aes_128_cbc}}, + {{"aes_cbc256"}, {&EVP_aes_256_cbc}}, + {{"aes_cfb8"}, {&EVP_aes_128_cfb8}}, + {{"aes_cfb128"}, {&EVP_aes_128_cfb128}}, + {{"aes_ecb"}, {&EVP_aes_128_ecb}, 16}, + {{"aes_ecb"}, {&EVP_aes_192_ecb}, 24}, + {{"aes_ecb"}, {&EVP_aes_256_ecb}, 32}, + {{NULL}} }; static struct cipher_type_t* get_cipher_type(ERL_NIF_TERM type, size_t key_len); @@ -829,6 +839,15 @@ static ERL_NIF_TERM info_lib(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] ver_term)); } +static ERL_NIF_TERM make_badarg_maybe(ErlNifEnv* env) +{ + ERL_NIF_TERM reason; + if (enif_has_pending_exception(env, &reason)) + return reason; /* dummy return value ignored */ + else + return enif_make_badarg(env); +} + static ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Type, Data) */ struct digest_type_t *digp = NULL; @@ -842,11 +861,11 @@ static ERL_NIF_TERM hash_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] !enif_inspect_iolist_as_binary(env, argv[1], &data)) { return enif_make_badarg(env); } - if (!digp->md_func) { + md = digp->md.p; + if (!md) { return atom_notsup; } - md = digp->md_func(); ret_size = (unsigned)EVP_MD_size(md); ASSERT(0 < ret_size && ret_size <= EVP_MAX_MD_SIZE); if (!EVP_Digest(data.data, data.size, @@ -872,12 +891,12 @@ static ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a if (!digp) { return enif_make_badarg(env); } - if (!digp->md_func) { + if (!digp->md.p) { return atom_notsup; } ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(EVP_MD_CTX)); - if (!EVP_DigestInit(ctx, digp->md_func())) { + if (!EVP_DigestInit(ctx, digp->md.p)) { enif_release_resource(ctx); return atom_notsup; } @@ -946,11 +965,11 @@ static ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a if (!digp) { return enif_make_badarg(env); } - if (!digp->md_func) { + if (!digp->md.p) { return atom_notsup; } - switch (EVP_MD_type(digp->md_func())) + switch (EVP_MD_type(digp->md.p)) { case NID_md4: ctx_size = MD4_CTX_LEN; @@ -1020,11 +1039,11 @@ static ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM !enif_inspect_iolist_as_binary(env, argv[1], &data)) { return enif_make_badarg(env); } - if (!digp->md_func) { + if (!digp->md.p) { return atom_notsup; } - switch (EVP_MD_type(digp->md_func())) + switch (EVP_MD_type(digp->md.p)) { case NID_md4: ctx_size = MD4_CTX_LEN; @@ -1102,11 +1121,11 @@ static ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM !enif_inspect_binary(env, tuple[1], &ctx)) { return enif_make_badarg(env); } - if (!digp->md_func) { + md = digp->md.p; + if (!md) { return atom_notsup; } - md = digp->md_func(); switch (EVP_MD_type(md)) { @@ -1186,8 +1205,8 @@ static ERL_NIF_TERM hmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] return enif_make_badarg(env); } - if (!digp->md_func || - !HMAC(digp->md_func(), + if (!digp->md.p || + !HMAC(digp->md.p, key.data, key.size, data.data, data.size, buff, &size)) { @@ -1229,7 +1248,7 @@ static ERL_NIF_TERM hmac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a !enif_inspect_iolist_as_binary(env, argv[1], &key)) { return enif_make_badarg(env); } - if (!digp->md_func) { + if (!digp->md.p) { return atom_notsup; } @@ -1239,12 +1258,12 @@ static ERL_NIF_TERM hmac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a #if OPENSSL_VERSION_NUMBER >= 0x1000000fL // Check the return value of HMAC_Init: it may fail in FIPS mode // for disabled algorithms - if (!HMAC_Init(&obj->ctx, key.data, key.size, digp->md_func())) { + if (!HMAC_Init(&obj->ctx, key.data, key.size, digp->md.p)) { enif_release_resource(obj); return atom_notsup; } #else - HMAC_Init(&obj->ctx, key.data, key.size, digp->md_func()); + HMAC_Init(&obj->ctx, key.data, key.size, digp->md.p); #endif ret = enif_make_resource(env, obj); @@ -1323,7 +1342,8 @@ static ERL_NIF_TERM block_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM || !enif_inspect_iolist_as_binary(env, argv[argc - 2], &text)) { return enif_make_badarg(env); } - if (!cipherp->cipher_func) { + cipher = cipherp->cipher.p; + if (!cipher) { return enif_raise_exception(env, atom_notsup); } @@ -1335,7 +1355,6 @@ static ERL_NIF_TERM block_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM return aes_cfb_8_crypt(env, argc-1, argv+1); } - cipher = cipherp->cipher_func(); ivec_size = EVP_CIPHER_iv_length(cipher); #ifdef HAVE_ECB_IVEC_BUG @@ -2110,27 +2129,31 @@ static void init_digest_types(ErlNifEnv* env) { struct digest_type_t* p = digest_types; - for (p = digest_types; p->type_str; p++) { - p->type_atom = enif_make_atom(env, p->type_str); + for (p = digest_types; p->type.str; p++) { + p->type.atom = enif_make_atom(env, p->type.str); + if (p->md.funcp) + p->md.p = p->md.funcp(); } - + p->type.atom = atom_false; /* end marker */ } static void init_cipher_types(ErlNifEnv* env) { struct cipher_type_t* p = cipher_types; - for (p = cipher_types; p->type_str; p++) { - p->type_atom = enif_make_atom(env, p->type_str); + for (p = cipher_types; p->type.str; p++) { + p->type.atom = enif_make_atom(env, p->type.str); + if (p->cipher.funcp) + p->cipher.p = p->cipher.funcp(); } - + p->type.atom = atom_false; /* end marker */ } static struct digest_type_t* get_digest_type(ERL_NIF_TERM type) { struct digest_type_t* p = NULL; - for (p = digest_types; p->type_str; p++) { - if (type == p->type_atom) { + for (p = digest_types; p->type.atom != atom_false; p++) { + if (type == p->type.atom) { return p; } } @@ -2140,8 +2163,8 @@ static struct digest_type_t* get_digest_type(ERL_NIF_TERM type) static struct cipher_type_t* get_cipher_type(ERL_NIF_TERM type, size_t key_len) { struct cipher_type_t* p = NULL; - for (p = cipher_types; p->type_str; p++) { - if (type == p->type_atom && (!p->key_len || key_len == p->key_len)) { + for (p = cipher_types; p->type.atom != atom_false; p++) { + if (type == p->type.atom && (!p->key_len || key_len == p->key_len)) { return p; } } @@ -2166,12 +2189,12 @@ static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM if (!digp) { return enif_make_badarg(env); } - if (!digp->md_func) { + md = digp->md.p; + if (!md) { return atom_notsup; } rsa = RSA_new(); - md = digp->md_func(); if (!enif_inspect_binary(env, argv[1], &digest_bin) || digest_bin.size != EVP_MD_size(md) @@ -2329,10 +2352,10 @@ static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar if (!digp) { return enif_make_badarg(env); } - if (!digp->md_func) { + md = digp->md.p; + if (!md) { return atom_notsup; } - md = digp->md_func(); if (!enif_inspect_binary(env,argv[1],&digest_bin) || digest_bin.size != EVP_MD_size(md)) { @@ -2904,8 +2927,7 @@ static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg) EC_POINT *point = NULL; /* {Field, Prime, Point, Order, CoFactor} = Curve */ - if (enif_is_tuple(env, curve_arg) - && enif_get_tuple(env,curve_arg,&c_arity,&curve) + if (enif_get_tuple(env,curve_arg,&c_arity,&curve) && c_arity == 5 && get_bn_from_bin(env, curve[3], &bn_order) && (curve[4] != atom_none && get_bn_from_bin(env, curve[4], &cofactor))) { @@ -2942,9 +2964,11 @@ static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg) /* create the EC_GROUP structure */ group = EC_GROUP_new_curve_GFp(p, a, b, NULL); -#if !defined(OPENSSL_NO_EC2M) - } else if (f_arity == 3 && field[0] == atom_characteristic_two_field) { +#if defined(OPENSSL_NO_EC2M) + enif_raise_exception(env, atom_notsup); + goto out_err; +#else /* {characteristic_two_field, M, Basis} */ int b_arity = -1; @@ -3221,7 +3245,7 @@ static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM badarg: if (key) EC_KEY_free(key); - return enif_make_badarg(env); + return make_badarg_maybe(env); #else return atom_notsup; #endif @@ -3241,10 +3265,10 @@ static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM if (!digp) { return enif_make_badarg(env); } - if (!digp->md_func) { + md = digp->md.p; + if (!md) { return atom_notsup; } - md = digp->md_func(); len = EVP_MD_size(md); if (!enif_inspect_binary(env,argv[1],&digest_bin) @@ -3272,7 +3296,7 @@ static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM badarg: if (key) EC_KEY_free(key); - return enif_make_badarg(env); + return make_badarg_maybe(env); #else return atom_notsup; #endif @@ -3292,10 +3316,10 @@ static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER if (!digp) { return enif_make_badarg(env); } - if (!digp->md_func) { + md = digp->md.p; + if (!md) { return atom_notsup; } - md = digp->md_func(); len = EVP_MD_size(md); if (!enif_inspect_binary(env, argv[1], &digest_bin) @@ -3314,7 +3338,7 @@ static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER badarg: if (key) EC_KEY_free(key); - return enif_make_badarg(env); + return make_badarg_maybe(env); #else return atom_notsup; #endif @@ -3339,7 +3363,7 @@ static ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF EC_KEY *other_ecdh = NULL; if (!get_ec_key(env, argv[1], argv[2], atom_undefined, &key)) - return enif_make_badarg(env); + return make_badarg_maybe(env); group = EC_GROUP_dup(EC_KEY_get0_group(key)); priv_key = EC_KEY_get0_private_key(key); diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml index 25b427a036..2ff8554afd 100644 --- a/lib/inets/doc/src/notes.xml +++ b/lib/inets/doc/src/notes.xml @@ -33,7 +33,22 @@ <file>notes.xml</file> </header> - <section><title>Inets 6.2</title> + <section><title>Inets 6.2.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Mend ipv6_host_with_brackets option in httpc</p> + <p> + Own Id: OTP-13417</p> + </item> + </list> + </section> + +</section> + +<section><title>Inets 6.2</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/inets/examples/server_root/conf/8080.conf b/lib/inets/examples/server_root/conf/8080.conf index 48e66f0114..7b1b4a15b2 100644 --- a/lib/inets/examples/server_root/conf/8080.conf +++ b/lib/inets/examples/server_root/conf/8080.conf @@ -1,7 +1,7 @@ Port 8080 #ServerName your.server.net SocketType ip_comm -Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_include mod_dir mod_get mod_head mod_log mod_disk_log +Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log ServerAdmin [email protected] ServerRoot /var/tmp/server_root ErrorLog logs/error_log_8080 diff --git a/lib/inets/examples/server_root/conf/8888.conf b/lib/inets/examples/server_root/conf/8888.conf index 79bb7fcca4..042779fcd0 100644 --- a/lib/inets/examples/server_root/conf/8888.conf +++ b/lib/inets/examples/server_root/conf/8888.conf @@ -1,7 +1,7 @@ Port 8888 #ServerName your.server.net SocketType ip_comm -Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_include mod_dir mod_get mod_head mod_log mod_disk_log +Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log ServerAdmin [email protected] ServerRoot /var/tmp/server_root ErrorLog logs/error_log_8888 diff --git a/lib/inets/examples/server_root/conf/httpd.conf b/lib/inets/examples/server_root/conf/httpd.conf index f99563d14b..98920ebaa5 100644 --- a/lib/inets/examples/server_root/conf/httpd.conf +++ b/lib/inets/examples/server_root/conf/httpd.conf @@ -64,7 +64,7 @@ SocketType ip_comm # WARNING! Do not tamper with this directive unless you are familiar with # EWSAPI. -Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_responsecontrol mod_trace mod_range mod_head mod_include mod_dir mod_get mod_log mod_disk_log +Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_responsecontrol mod_trace mod_range mod_head mod_dir mod_get mod_log mod_disk_log # ServerAdmin: Your address, where problems with the server should be # e-mailed. diff --git a/lib/inets/examples/server_root/conf/ssl.conf b/lib/inets/examples/server_root/conf/ssl.conf index 8b8c57a98b..de49ceafd0 100644 --- a/lib/inets/examples/server_root/conf/ssl.conf +++ b/lib/inets/examples/server_root/conf/ssl.conf @@ -1,7 +1,7 @@ Port 8088 #ServerName your.server.net SocketType ssl -Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_include mod_dir mod_get mod_head mod_log mod_disk_log +Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log ServerAdmin [email protected] ServerRoot /var/tmp/server_root ErrorLog logs/error_log_8088 diff --git a/lib/inets/src/http_client/httpc.erl b/lib/inets/src/http_client/httpc.erl index 85663b5ded..4554881d79 100644 --- a/lib/inets/src/http_client/httpc.erl +++ b/lib/inets/src/http_client/httpc.erl @@ -556,7 +556,7 @@ handle_request(Method, Url, Request = #request{from = Receiver, scheme = Scheme, - address = {Host, Port}, + address = {host_address(Host, BracketedHost), Port}, path = MaybeEscPath, pquery = MaybeEscQuery, method = Method, @@ -1268,3 +1268,7 @@ child_name(Pid, [_ | Children]) -> %% d(_, _, _) -> %% ok. +host_address(Host, false) -> + Host; +host_address(Host, true) -> + string:strip(string:strip(Host, right, $]), left, $[). diff --git a/lib/inets/src/http_client/httpc_request.erl b/lib/inets/src/http_client/httpc_request.erl index af4c3f75f2..8fcfbc30c0 100644 --- a/lib/inets/src/http_client/httpc_request.erl +++ b/lib/inets/src/http_client/httpc_request.erl @@ -186,16 +186,19 @@ is_client_closing(Headers) -> %%%======================================================================== %%% Internal functions %%%======================================================================== -post_data(Method, Headers, {ContentType, Body}, HeadersAsIs) - when (Method =:= post) orelse (Method =:= put) - orelse (Method =:= patch) -> +post_data(Method, Headers, {ContentType, Body}, HeadersAsIs) + when (Method =:= post) + orelse (Method =:= put) + orelse (Method =:= patch) + orelse (Method =:= delete) -> + NewBody = case Headers#http_request_h.expect of - "100-continue" -> - ""; - _ -> - Body - end, - + "100-continue" -> + ""; + _ -> + Body + end, + NewHeaders = case HeadersAsIs of [] -> Headers#http_request_h{ @@ -213,7 +216,7 @@ post_data(Method, Headers, {ContentType, Body}, HeadersAsIs) _ -> HeadersAsIs end, - + {NewHeaders, NewBody}; post_data(_, Headers, _, []) -> diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src index a9fbb1c3f7..6baecfe7a4 100644 --- a/lib/inets/src/inets_app/inets.appup.src +++ b/lib/inets/src/inets_app/inets.appup.src @@ -18,10 +18,12 @@ %% %CopyrightEnd% {"%VSN%", [ + {<<"6.2">>, [{load_module, httpc, soft_purge, soft_purge, []}]}, {<<"6\\..*">>,[{restart_application, inets}]}, {<<"5\\..*">>,[{restart_application, inets}]} ], [ + {<<"6.2">>, [{load_module, httpc, soft_purge, soft_purge, []}]}, {<<"6\\..*">>,[{restart_application, inets}]}, {<<"5\\..*">>,[{restart_application, inets}]} ] diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index 93b96e101f..f9b3aa5b59 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -67,6 +67,7 @@ real_requests()-> head, get, post, + delete, post_stream, patch, async, @@ -256,6 +257,29 @@ post(Config) when is_list(Config) -> {ok, {{_,504,_}, [_ | _], []}} = httpc:request(post, {URL, [{"expect","100-continue"}], "text/plain", "foobar"}, [], []). +%%-------------------------------------------------------------------- +delete() -> + [{"Test http delete request against local server. We do in this case " + "only care about the client side of the the delete. The server " + "script will not actually use the delete data."}]. +delete(Config) when is_list(Config) -> + CGI = case test_server:os_type() of + {win32, _} -> + "/cgi-bin/cgi_echo.exe"; + _ -> + "/cgi-bin/cgi_echo" + end, + + URL = url(group_name(Config), CGI, Config), + Body = lists:duplicate(100, "1"), + + {ok, {{_,200,_}, [_ | _], [_ | _]}} = + httpc:request(delete, {URL, [{"expect","100-continue"}], + "text/plain", Body}, [], []), + + {ok, {{_,504,_}, [_ | _], []}} = + httpc:request(delete, {URL, [{"expect","100-continue"}], + "text/plain", "foobar"}, [], []). %%-------------------------------------------------------------------- patch() -> diff --git a/lib/inets/test/httpd_1_1.erl b/lib/inets/test/httpd_1_1.erl index d3a1e3672a..88d91b552c 100644 --- a/lib/inets/test/httpd_1_1.erl +++ b/lib/inets/test/httpd_1_1.erl @@ -233,14 +233,6 @@ trace(Type, Port, Host, Node)-> "Max-Forwards:2\r\n\r\n", [{statuscode, 200}]). head(Type, Port, Host, Node)-> - %% mod_include - ok = httpd_test_lib:verify_request(Type, Host, Port, Node, - "HEAD /fsize.shtml HTTP/1.0\r\n\r\n", - [{statuscode, 200}, - {version, "HTTP/1.0"}]), - ok = httpd_test_lib:verify_request(Type, Host, Port, Node, - "HEAD /fsize.shtml HTTP/1.1\r\nhost:" ++ - Host ++ "\r\n\r\n", [{statuscode, 200}]), %% mod_esi ok = httpd_test_lib:verify_request(Type, Host, Port, Node, "HEAD /cgi-bin/erl/httpd_example/newformat" diff --git a/lib/inets/test/httpd_test_data/server_root/conf/8080.conf b/lib/inets/test/httpd_test_data/server_root/conf/8080.conf index 48e66f0114..7b1b4a15b2 100644 --- a/lib/inets/test/httpd_test_data/server_root/conf/8080.conf +++ b/lib/inets/test/httpd_test_data/server_root/conf/8080.conf @@ -1,7 +1,7 @@ Port 8080 #ServerName your.server.net SocketType ip_comm -Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_include mod_dir mod_get mod_head mod_log mod_disk_log +Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log ServerAdmin [email protected] ServerRoot /var/tmp/server_root ErrorLog logs/error_log_8080 diff --git a/lib/inets/test/httpd_test_data/server_root/conf/8888.conf b/lib/inets/test/httpd_test_data/server_root/conf/8888.conf index 79bb7fcca4..042779fcd0 100644 --- a/lib/inets/test/httpd_test_data/server_root/conf/8888.conf +++ b/lib/inets/test/httpd_test_data/server_root/conf/8888.conf @@ -1,7 +1,7 @@ Port 8888 #ServerName your.server.net SocketType ip_comm -Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_include mod_dir mod_get mod_head mod_log mod_disk_log +Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log ServerAdmin [email protected] ServerRoot /var/tmp/server_root ErrorLog logs/error_log_8888 diff --git a/lib/inets/test/httpd_test_data/server_root/conf/httpd.conf b/lib/inets/test/httpd_test_data/server_root/conf/httpd.conf index 87c2973e5a..d94b245c25 100644 --- a/lib/inets/test/httpd_test_data/server_root/conf/httpd.conf +++ b/lib/inets/test/httpd_test_data/server_root/conf/httpd.conf @@ -64,7 +64,7 @@ SocketType ip_comm # WARNING! Do not tamper with this directive unless you are familiar with # EWSAPI. -Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_responsecontrol mod_trace mod_range mod_head mod_include mod_dir mod_get mod_log mod_disk_log +Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_responsecontrol mod_trace mod_range mod_head mod_dir mod_get mod_log mod_disk_log # ServerAdmin: Your address, where problems with the server should be # e-mailed. diff --git a/lib/inets/test/httpd_test_data/server_root/conf/ssl.conf b/lib/inets/test/httpd_test_data/server_root/conf/ssl.conf index 8b8c57a98b..de49ceafd0 100644 --- a/lib/inets/test/httpd_test_data/server_root/conf/ssl.conf +++ b/lib/inets/test/httpd_test_data/server_root/conf/ssl.conf @@ -1,7 +1,7 @@ Port 8088 #ServerName your.server.net SocketType ssl -Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_include mod_dir mod_get mod_head mod_log mod_disk_log +Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log ServerAdmin [email protected] ServerRoot /var/tmp/server_root ErrorLog logs/error_log_8088 diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8080.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8080.conf index 48e66f0114..7b1b4a15b2 100644 --- a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8080.conf +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8080.conf @@ -1,7 +1,7 @@ Port 8080 #ServerName your.server.net SocketType ip_comm -Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_include mod_dir mod_get mod_head mod_log mod_disk_log +Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log ServerAdmin [email protected] ServerRoot /var/tmp/server_root ErrorLog logs/error_log_8080 diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8888.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8888.conf index 79bb7fcca4..042779fcd0 100644 --- a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8888.conf +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/8888.conf @@ -1,7 +1,7 @@ Port 8888 #ServerName your.server.net SocketType ip_comm -Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_include mod_dir mod_get mod_head mod_log mod_disk_log +Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log ServerAdmin [email protected] ServerRoot /var/tmp/server_root ErrorLog logs/error_log_8888 diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/httpd.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/httpd.conf index 87c2973e5a..d94b245c25 100644 --- a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/httpd.conf +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/httpd.conf @@ -64,7 +64,7 @@ SocketType ip_comm # WARNING! Do not tamper with this directive unless you are familiar with # EWSAPI. -Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_responsecontrol mod_trace mod_range mod_head mod_include mod_dir mod_get mod_log mod_disk_log +Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_responsecontrol mod_trace mod_range mod_head mod_dir mod_get mod_log mod_disk_log # ServerAdmin: Your address, where problems with the server should be # e-mailed. diff --git a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/ssl.conf b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/ssl.conf index 8b8c57a98b..de49ceafd0 100644 --- a/lib/inets/test/old_httpd_SUITE_data/server_root/conf/ssl.conf +++ b/lib/inets/test/old_httpd_SUITE_data/server_root/conf/ssl.conf @@ -1,7 +1,7 @@ Port 8088 #ServerName your.server.net SocketType ssl -Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_include mod_dir mod_get mod_head mod_log mod_disk_log +Modules mod_alias mod_auth mod_esi mod_actions mod_cgi mod_dir mod_get mod_head mod_log mod_disk_log ServerAdmin [email protected] ServerRoot /var/tmp/server_root ErrorLog logs/error_log_8088 diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk index 3d25b328af..df2359e012 100644 --- a/lib/inets/vsn.mk +++ b/lib/inets/vsn.mk @@ -19,6 +19,6 @@ # %CopyrightEnd% APPLICATION = inets -INETS_VSN = 6.2 +INETS_VSN = 6.2.1 PRE_VSN = APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)" diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl index 149cc6c816..a3036f011c 100644 --- a/lib/kernel/test/prim_file_SUITE.erl +++ b/lib/kernel/test/prim_file_SUITE.erl @@ -1025,17 +1025,15 @@ file_write_file_info_opts(Config) when is_list(Config) -> %% REM: determine date range dependent on time_t = Uint32 | Sint32 | Sint64 %% Determine time_t on os:type()? - lists:foreach(fun - ({FI, Opts}) -> + lists:foreach(fun ({FI, Opts}) -> ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI, Opts]) - end, [ - {#file_info{ mode=8#400, atime = Time, mtime = Time, ctime = Time}, Opts} || + end, [ {#file_info{ mode=8#400, atime = Time, mtime = Time, ctime = Time}, Opts} || Opts <- [[{time, universal}],[{time, local}]], Time <- [ {{1970,1,1},{0,0,0}}, {{1970,1,1},{0,0,1}}, - {{1969,12,31},{23,59,59}}, - {{1908,2,3},{23,59,59}}, + % {{1969,12,31},{23,59,59}}, + % {{1908,2,3},{23,59,59}}, {{2012,2,3},{23,59,59}}, {{2037,2,3},{23,59,59}}, erlang:localtime() @@ -1070,8 +1068,9 @@ file_write_read_file_info_opts(Config) when is_list(Config) -> ok = file_write_read_file_info_opts(Handle, Name, {{1989, 04, 28}, {19,30,22}}, [{time, local}]), ok = file_write_read_file_info_opts(Handle, Name, {{1989, 04, 28}, {19,30,22}}, [{time, universal}]), - ok = file_write_read_file_info_opts(Handle, Name, {{1930, 04, 28}, {19,30,22}}, [{time, local}]), - ok = file_write_read_file_info_opts(Handle, Name, {{1930, 04, 28}, {19,30,22}}, [{time, universal}]), + %% will not work on platforms with unsigned time_t + %ok = file_write_read_file_info_opts(Handle, Name, {{1930, 04, 28}, {19,30,22}}, [{time, local}]), + %ok = file_write_read_file_info_opts(Handle, Name, {{1930, 04, 28}, {19,30,22}}, [{time, universal}]), ok = file_write_read_file_info_opts(Handle, Name, 1, [{time, posix}]), ok = file_write_read_file_info_opts(Handle, Name, -1, [{time, posix}]), ok = file_write_read_file_info_opts(Handle, Name, 300000, [{time, posix}]), @@ -1085,7 +1084,9 @@ file_write_read_file_info_opts(Handle, Name, Mtime, Opts) -> {ok, FI} = ?PRIM_FILE_call(read_file_info, Handle, [Name, Opts]), FI2 = FI#file_info{ mtime = Mtime }, ok = ?PRIM_FILE_call(write_file_info, Handle, [Name, FI2, Opts]), - {ok, FI2} = ?PRIM_FILE_call(read_file_info, Handle, [Name, Opts]), + {ok, FI3} = ?PRIM_FILE_call(read_file_info, Handle, [Name, Opts]), + io:format("Expecting mtime = ~p, got ~p~n", [FI2#file_info.mtime, FI3#file_info.mtime]), + FI2 = FI3, ok. diff --git a/lib/mnesia/doc/src/notes.xml b/lib/mnesia/doc/src/notes.xml index 149cd69559..18bb110104 100644 --- a/lib/mnesia/doc/src/notes.xml +++ b/lib/mnesia/doc/src/notes.xml @@ -39,7 +39,23 @@ thus constitutes one section in this document. The title of each section is the version number of Mnesia.</p> - <section><title>Mnesia 4.13.3</title> + <section><title>Mnesia 4.13.4</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Mnesia transactions could hang while waiting on a + response from a node who had stopped.</p> + <p> + Own Id: OTP-13423</p> + </item> + </list> + </section> + +</section> + +<section><title>Mnesia 4.13.3</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/mnesia/src/mnesia_tm.erl b/lib/mnesia/src/mnesia_tm.erl index e7ee938312..1d3eb87036 100644 --- a/lib/mnesia/src/mnesia_tm.erl +++ b/lib/mnesia/src/mnesia_tm.erl @@ -1692,13 +1692,10 @@ commit_participant(Coord, Tid, Bin, C0, DiscNs, _RamNs) -> ?eval_debug_fun({?MODULE, commit_participant, undo_prepare}, [{tid, Tid}]); - {'EXIT', _, _} -> + {'EXIT', _MnesiaTM, Reason} -> + reply(Coord, {do_abort, Tid, self(), {bad_commit,Reason}}), mnesia_recover:log_decision(D#decision{outcome = aborted}), - ?eval_debug_fun({?MODULE, commit_participant, exit_log_abort}, - [{tid, Tid}]), - mnesia_schema:undo_prepare_commit(Tid, C0), - ?eval_debug_fun({?MODULE, commit_participant, exit_undo_prepare}, - [{tid, Tid}]); + mnesia_schema:undo_prepare_commit(Tid, C0); Msg -> verbose("** ERROR ** commit_participant ~p, got unexpected msg: ~p~n", @@ -2210,8 +2207,6 @@ reconfigure_coordinators(N, [{Tid, [Store | _]} | Coordinators]) -> true -> send_mnesia_down(Tid, Store, N) end; - aborted -> - ignore; % avoid spurious mnesia_down messages _ -> %% Tell the coordinator about the mnesia_down send_mnesia_down(Tid, Store, N) diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk index 843d9d18d4..194bc439a0 100644 --- a/lib/mnesia/vsn.mk +++ b/lib/mnesia/vsn.mk @@ -1 +1 @@ -MNESIA_VSN = 4.13.3 +MNESIA_VSN = 4.13.4 diff --git a/lib/os_mon/test/cpu_sup_SUITE.erl b/lib/os_mon/test/cpu_sup_SUITE.erl index 13d47c6a89..69c7414630 100644 --- a/lib/os_mon/test/cpu_sup_SUITE.erl +++ b/lib/os_mon/test/cpu_sup_SUITE.erl @@ -21,7 +21,7 @@ -include_lib("common_test/include/ct.hrl"). %% Test server specific exports --export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]). +-export([all/0, suite/0]). -export([init_per_suite/1, end_per_suite/1]). -export([init_per_testcase/2, end_per_testcase/2]). @@ -31,186 +31,163 @@ -export([port/1]). -export([terminate/1, unavailable/1, restart/1]). -%% Default timetrap timeout (set in init_per_testcase) --define(default_timeout, ?t:minutes(1)). - init_per_suite(Config) when is_list(Config) -> - ?line ok = application:start(os_mon), + ok = application:start(os_mon), Config. end_per_suite(Config) when is_list(Config) -> - ?line ok = application:stop(os_mon), + ok = application:stop(os_mon), Config. init_per_testcase(unavailable, Config) -> terminate(Config), init_per_testcase(dummy, Config); init_per_testcase(_Case, Config) -> - Dog = ?t:timetrap(?default_timeout), - [{watchdog, Dog} | Config]. + Config. end_per_testcase(unavailable, Config) -> restart(Config), end_per_testcase(dummy, Config); -end_per_testcase(_Case, Config) -> - Dog = ?config(watchdog, Config), - ?t:timetrap_cancel(Dog), +end_per_testcase(_Case, _Config) -> ok. -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> case test_server:os_type() of - {unix, sunos} -> - [load_api, util_api, util_values, port, unavailable]; - {unix, linux} -> - [load_api, util_api, util_values, port, unavailable]; - {unix, freebsd} -> - [load_api, util_api, util_values, port, unavailable]; - {unix, _OSname} -> [load_api]; - _OS -> [unavailable] + {unix, sunos} -> + [load_api, util_api, util_values, port, unavailable]; + {unix, linux} -> + [load_api, util_api, util_values, port, unavailable]; + {unix, freebsd} -> + [load_api, util_api, util_values, port, unavailable]; + {unix, _OSname} -> [load_api]; + _OS -> [unavailable] end. -groups() -> - []. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - - -load_api(suite) -> - []; -load_api(doc) -> - ["Test of load API functions"]; +%% Test of load API functions load_api(Config) when is_list(Config) -> %% nprocs() - ?line N = cpu_sup:nprocs(), - ?line true = is_integer(N), - ?line true = N>0, - ?line true = N<1000000, + N = cpu_sup:nprocs(), + true = is_integer(N), + true = N>0, + true = N<1000000, %% avg1() - ?line Load1 = cpu_sup:avg1(), - ?line true = is_integer(Load1), - ?line true = Load1>0, + Load1 = cpu_sup:avg1(), + true = is_integer(Load1), + true = Load1>0, %% avg5() - ?line Load5 = cpu_sup:avg5(), - ?line true = is_integer(Load5), - ?line true = Load5>0, + Load5 = cpu_sup:avg5(), + true = is_integer(Load5), + true = Load5>0, %% avg15() - ?line Load15 = cpu_sup:avg15(), - ?line true = is_integer(Load15), - ?line true = Load15>0, + Load15 = cpu_sup:avg15(), + true = is_integer(Load15), + true = Load15>0, ok. -util_api(suite) -> - []; -util_api(doc) -> - ["Test of utilization API functions"]; +%% Test of utilization API functions util_api(Config) when is_list(Config) -> %% Some useful funs when testing util/1 BusyP = fun({user, _Share}) -> true; - ({nice_user, _Share}) -> true; - ({kernel, _Share}) -> true; - ({hard_irq, _Share}) -> true; - ({soft_irq, _Share}) -> true; - (_) -> false - end, + ({nice_user, _Share}) -> true; + ({kernel, _Share}) -> true; + ({hard_irq, _Share}) -> true; + ({soft_irq, _Share}) -> true; + (_) -> false + end, NonBusyP = fun({wait, _Share}) -> true; - ({idle, _Share}) -> true; - ({steal, _Share}) -> true; - (_) -> false - end, + ({idle, _Share}) -> true; + ({steal, _Share}) -> true; + (_) -> false + end, Sum = fun({_Tag, X}, Acc) -> Acc+X end, %% util() - ?line Util1 = cpu_sup:util(), - ?line true = is_number(Util1), - ?line true = Util1>0, - ?line Util2 = cpu_sup:util(), - ?line true = is_number(Util2), - ?line true = Util2>0, + Util1 = cpu_sup:util(), + true = is_number(Util1), + true = Util1>0, + Util2 = cpu_sup:util(), + true = is_number(Util2), + true = Util2>0, %% util([]) - ?line {all, Busy1, NonBusy1, []} = cpu_sup:util([]), - ?line 100.00 = Busy1 + NonBusy1, + {all, Busy1, NonBusy1, []} = cpu_sup:util([]), + 100.00 = Busy1 + NonBusy1, %% util([detailed]) - ?line {Cpus2, Busy2, NonBusy2, []} = cpu_sup:util([detailed]), - ?line true = lists:all(fun(X) -> is_integer(X) end, Cpus2), - ?line true = lists:all(BusyP, Busy2), - ?line true = lists:all(NonBusyP, NonBusy2), - ?line 100.00 = lists:foldl(Sum,0,Busy2)+lists:foldl(Sum,0,NonBusy2), + {Cpus2, Busy2, NonBusy2, []} = cpu_sup:util([detailed]), + true = lists:all(fun(X) -> is_integer(X) end, Cpus2), + true = lists:all(BusyP, Busy2), + true = lists:all(NonBusyP, NonBusy2), + 100.00 = lists:foldl(Sum,0,Busy2)+lists:foldl(Sum,0,NonBusy2), %% util([per_cpu]) - ?line [{Cpu3, Busy3, NonBusy3, []}|_] = cpu_sup:util([per_cpu]), - ?line true = is_integer(Cpu3), - ?line 100.00 = Busy3 + NonBusy3, + [{Cpu3, Busy3, NonBusy3, []}|_] = cpu_sup:util([per_cpu]), + true = is_integer(Cpu3), + 100.00 = Busy3 + NonBusy3, %% util([detailed, per_cpu]) - ?line [{Cpu4, Busy4, NonBusy4, []}|_] = - cpu_sup:util([detailed, per_cpu]), - ?line true = is_integer(Cpu4), - ?line true = lists:all(BusyP, Busy2), - ?line true = lists:all(NonBusyP, NonBusy2), - ?line 100.00 = lists:foldl(Sum,0,Busy4)+lists:foldl(Sum,0,NonBusy4), + [{Cpu4, Busy4, NonBusy4, []}|_] = + cpu_sup:util([detailed, per_cpu]), + true = is_integer(Cpu4), + true = lists:all(BusyP, Busy2), + true = lists:all(NonBusyP, NonBusy2), + 100.00 = lists:foldl(Sum,0,Busy4)+lists:foldl(Sum,0,NonBusy4), %% bad util/1 calls - ?line {'EXIT',{badarg,_}} = (catch cpu_sup:util(detailed)), - ?line {'EXIT',{badarg,_}} = (catch cpu_sup:util([detialed])), + {'EXIT',{badarg,_}} = (catch cpu_sup:util(detailed)), + {'EXIT',{badarg,_}} = (catch cpu_sup:util([detialed])), ok. -define(SPIN_TIME, 1000). -util_values(suite) -> - []; -util_values(doc) -> - ["Test utilization values"]; +%% Test utilization values util_values(Config) when is_list(Config) -> Tester = self(), Ref = make_ref(), Loop = fun (L) -> L(L) end, Spinner = fun () -> - Looper = spawn_link(fun () -> Loop(Loop) end), - receive after ?SPIN_TIME -> ok end, - unlink(Looper), - exit(Looper, kill), - Tester ! Ref - end, + Looper = spawn_link(fun () -> Loop(Loop) end), + receive after ?SPIN_TIME -> ok end, + unlink(Looper), + exit(Looper, kill), + Tester ! Ref + end, - ?line cpu_sup:util(), + cpu_sup:util(), - ?line spawn_link(Spinner), - ?line receive Ref -> ok end, - ?line HighUtil1 = cpu_sup:util(), + spawn_link(Spinner), + receive Ref -> ok end, + HighUtil1 = cpu_sup:util(), - ?line receive after ?SPIN_TIME -> ok end, - ?line LowUtil1 = cpu_sup:util(), + receive after ?SPIN_TIME -> ok end, + LowUtil1 = cpu_sup:util(), - ?line spawn_link(Spinner), - ?line receive Ref -> ok end, - ?line HighUtil2 = cpu_sup:util(), + spawn_link(Spinner), + receive Ref -> ok end, + HighUtil2 = cpu_sup:util(), - ?line receive after ?SPIN_TIME -> ok end, - ?line LowUtil2 = cpu_sup:util(), + receive after ?SPIN_TIME -> ok end, + LowUtil2 = cpu_sup:util(), Utils = [{high1,HighUtil1}, {low1,LowUtil1}, - {high2,HighUtil2}, {low2,LowUtil2}], - ?t:format("Utils: ~p~n", [Utils]), + {high2,HighUtil2}, {low2,LowUtil2}], + io:format("Utils: ~p~n", [Utils]), - ?line false = LowUtil1 > HighUtil1, - ?line false = LowUtil1 > HighUtil2, - ?line false = LowUtil2 > HighUtil1, - ?line false = LowUtil2 > HighUtil2, + false = LowUtil1 > HighUtil1, + false = LowUtil1 > HighUtil2, + false = LowUtil2 > HighUtil1, + false = LowUtil2 > HighUtil2, ok. @@ -218,76 +195,66 @@ util_values(Config) when is_list(Config) -> % Outdated % The portprogram is now restarted if killed, and not by os_mon... -port(suite) -> - []; -port(doc) -> - ["Test that cpu_sup handles a terminating port program"]; +%% Test that cpu_sup handles a terminating port program port(Config) when is_list(Config) -> case cpu_sup_os_pid() of - {ok, PidStr} -> - %% Monitor cpu_sup - ?line MonRef = erlang:monitor(process, cpu_sup), - ?line N1 = cpu_sup:nprocs(), - ?line true = N1>0, - - %% Kill the port program - case os:cmd("kill -9 " ++ PidStr) of - [] -> - %% cpu_sup should not terminate - receive - {'DOWN', MonRef, _, _, Reason} -> - ?line ?t:fail({unexpected_exit_reason, Reason}) - after 3000 -> - ok - end, - - %% Give cpu_sup time to restart cpu_sup port - ?t:sleep(?t:seconds(3)), - ?line N2 = cpu_sup:nprocs(), - ?line true = N2>0, - - erlang:demonitor(MonRef), - ok; - - Line -> - erlang:demonitor(MonRef), - {skip, {not_killed, Line}} - end; - _ -> - {skip, os_pid_not_found } + {ok, PidStr} -> + %% Monitor cpu_sup + MonRef = erlang:monitor(process, cpu_sup), + N1 = cpu_sup:nprocs(), + true = N1>0, + + %% Kill the port program + case os:cmd("kill -9 " ++ PidStr) of + [] -> + %% cpu_sup should not terminate + receive + {'DOWN', MonRef, _, _, Reason} -> + ct:fail({unexpected_exit_reason, Reason}) + after 3000 -> + ok + end, + + %% Give cpu_sup time to restart cpu_sup port + ct:sleep({seconds, 3}), + N2 = cpu_sup:nprocs(), + true = N2>0, + + erlang:demonitor(MonRef), + ok; + + Line -> + erlang:demonitor(MonRef), + {skip, {not_killed, Line}} + end; + _ -> + {skip, os_pid_not_found } end. -terminate(suite) -> - []; terminate(Config) when is_list(Config) -> ok = application:set_env(os_mon, start_cpu_sup, false), _ = supervisor:terminate_child(os_mon_sup, cpu_sup), ok. -unavailable(suite) -> - []; -unavailable(doc) -> - ["Test correct behaviour when service is unavailable"]; +%% Test correct behaviour when service is unavailable unavailable(Config) when is_list(Config) -> %% Make sure all API functions return their dummy values - ?line 0 = cpu_sup:nprocs(), - ?line 0 = cpu_sup:avg1(), - ?line 0 = cpu_sup:avg5(), - ?line 0 = cpu_sup:avg15(), - ?line 0 = cpu_sup:util(), - ?line {all,0,0,[]} = cpu_sup:util([]), - ?line {all,0,0,[]} = cpu_sup:util([detailed]), - ?line {all,0,0,[]} = cpu_sup:util([per_cpu]), - ?line {all,0,0,[]} = cpu_sup:util([detailed,per_cpu]), + 0 = cpu_sup:nprocs(), + 0 = cpu_sup:avg1(), + 0 = cpu_sup:avg5(), + 0 = cpu_sup:avg15(), + 0 = cpu_sup:util(), + {all,0,0,[]} = cpu_sup:util([]), + {all,0,0,[]} = cpu_sup:util([detailed]), + {all,0,0,[]} = cpu_sup:util([per_cpu]), + {all,0,0,[]} = cpu_sup:util([detailed,per_cpu]), ok. -restart(suite) -> - []; restart(Config) when is_list(Config) -> - ?line ok = application:set_env(os_mon, start_cpu_sup, true), - ?line {ok, _Pid} = supervisor:restart_child(os_mon_sup, cpu_sup), + ok = application:set_env(os_mon, start_cpu_sup, true), + {ok, _Pid} = supervisor:restart_child(os_mon_sup, cpu_sup), ok. %% Aux @@ -295,6 +262,6 @@ restart(Config) when is_list(Config) -> cpu_sup_os_pid() -> Str = os:cmd("ps -e | grep '[c]pu_sup'"), case io_lib:fread("~s", Str) of - {ok, [Pid], _Rest} -> {ok, Pid}; - _ -> {error, pid_not_found} + {ok, [Pid], _Rest} -> {ok, Pid}; + _ -> {error, pid_not_found} end. diff --git a/lib/os_mon/test/disksup_SUITE.erl b/lib/os_mon/test/disksup_SUITE.erl index 8e2825ec26..bd90093d29 100644 --- a/lib/os_mon/test/disksup_SUITE.erl +++ b/lib/os_mon/test/disksup_SUITE.erl @@ -21,7 +21,7 @@ -include_lib("common_test/include/ct.hrl"). %% Test server specific exports --export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]). +-export([all/0, suite/0]). -export([init_per_suite/1, end_per_suite/1]). -export([init_per_testcase/2, end_per_testcase/2]). @@ -32,9 +32,6 @@ -export([otp_5910/1]). -export([posix_only/1]). -%% Default timetrap timeout (set in init_per_testcase) --define(default_timeout, ?t:minutes(1)). - init_per_suite(Config) when is_list(Config) -> ok = application:start(os_mon), Config. @@ -47,19 +44,18 @@ init_per_testcase(unavailable, Config) -> terminate(Config), init_per_testcase(dummy, Config); init_per_testcase(_Case, Config) -> - Dog = ?t:timetrap(?default_timeout), - [{watchdog,Dog} | Config]. + Config. end_per_testcase(TC, Config) when TC =:= unavailable; TC =:= posix_only -> restart(Config), end_per_testcase(dummy, Config); -end_per_testcase(_Case, Config) -> - Dog = ?config(watchdog, Config), - ?t:timetrap_cancel(Dog), +end_per_testcase(_Case, _Config) -> ok. -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> Bugs = [otp_5910], @@ -70,18 +66,7 @@ all() -> _OS -> [unavailable] end. -groups() -> - []. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - - -api(suite) -> []; -api(doc) -> ["Test of API functions"]; +%% Test of API functions api(Config) when is_list(Config) -> %% get_disk_data() @@ -110,8 +95,7 @@ api(Config) when is_list(Config) -> ok. -config(suite) -> []; -config(doc) -> ["Test configuration"]; +%% Test configuration config(Config) when is_list(Config) -> %% Change configuration parameters and make sure change is reflected @@ -147,8 +131,8 @@ config(Config) when is_list(Config) -> %% changes too much during its course, or if there are timing problems %% with the alarm_handler receiving the alarms too late %%---------------------------------------------------------------------- -alarm(suite) -> []; -alarm(doc) -> ["Test that alarms are set and cleared"]; + +%% Test that alarms are set and cleared alarm(Config) when is_list(Config) -> %% Find out how many disks exceed the threshold @@ -162,7 +146,7 @@ alarm(Config) when is_list(Config) -> true; true -> dump_info(), - ?t:fail({bad_alarms, Threshold1, Data1, Alarms1}) + ct:fail({bad_alarms, Threshold1, Data1, Alarms1}) end, %% Try to find a disk with space usage below Threshold1, @@ -187,7 +171,7 @@ alarm(Config) when is_list(Config) -> true; true -> dump_info(), - ?t:fail({bad_alarms, Threshold2, Data2, Alarms2}) + ct:fail({bad_alarms, Threshold2, Data2, Alarms2}) end; false -> ignore @@ -215,7 +199,7 @@ alarm(Config) when is_list(Config) -> ok; true -> dump_info(), - ?t:fail({bad_alarms, Threshold3, Data3, Alarms3}) + ct:fail({bad_alarms, Threshold3, Data3, Alarms3}) end; 100 -> ignore @@ -271,9 +255,7 @@ until(Fun, [H|T]) -> end; until(_Fun, []) -> false. -port(suite) -> []; -port(doc) -> - ["Test that disksup handles a terminating port program"]; +%% Test that disksup handles a terminating port program port(Config) when is_list(Config) -> Str = os:cmd("ps -ef | grep '[d]isksup'"), case io_lib:fread("~s ~s", Str) of @@ -293,14 +275,14 @@ port(Config) when is_list(Config) -> {'DOWN', MonRef, _, _, {port_died, _Reason}} -> ok; {'DOWN', MonRef, _, _, Reason} -> - ?t:fail({unexpected_exit_reason, Reason}) + ct:fail({unexpected_exit_reason, Reason}) after 3000 -> - ?t:fail({still_alive, Str}) + ct:fail({still_alive, Str}) end, %% Give os_mon_sup time to restart disksup - ?t:sleep(?t:seconds(3)), + ct:sleep({seconds,3}), [{_Disk2,Kbyte2,_Cap2}|_] = disksup:get_disk_data(), true = Kbyte2>0, @@ -314,15 +296,12 @@ port(Config) when is_list(Config) -> {skip, {os_pid_not_found, Str}} end. -terminate(suite) -> []; terminate(Config) when is_list(Config) -> ok = application:set_env(os_mon, start_disksup, false), ok = supervisor:terminate_child(os_mon_sup, disksup), ok. -unavailable(suite) -> []; -unavailable(doc) -> - ["Test correct behaviour when service is unavailable"]; +%% Test correct behaviour when service is unavailable unavailable(Config) when is_list(Config) -> %% Make sure all API functions return their dummy values @@ -333,18 +312,16 @@ unavailable(Config) when is_list(Config) -> ok = disksup:set_almost_full_threshold(0.9), ok. -restart(suite) -> - []; restart(Config) when is_list(Config) -> ok = application:set_env(os_mon, start_disksup, true), ok = application:set_env(os_mon, disksup_posix_only, false), - {ok, _Pid} = supervisor:restart_child(os_mon_sup, disksup), - ok. + case supervisor:restart_child(os_mon_sup, disksup) of + {ok, _Pid} -> ok; + {error, running} -> ok + end. -otp_5910(suite) -> []; -otp_5910(doc) -> - ["Test that alarms are cleared if disksup crashes or " - "if OS_Mon is stopped"]; +%% Test that alarms are cleared if disksup crashes or +%% if OS_Mon is stopped otp_5910(Config) when is_list(Config) -> %% Make sure disksup sets at least one alarm @@ -365,12 +342,12 @@ otp_5910(Config) when is_list(Config) -> Alarms = get_alarms(), if Over==0 -> - ?t:fail({threshold_too_low, Data2, Threshold}); + ct:fail({threshold_too_low, Data2, Threshold}); Over==length(Alarms) -> ok; true -> dump_info(), - ?t:fail({bad_alarms, Threshold, Data2, Alarms}) + ct:fail({bad_alarms, Threshold, Data2, Alarms}) end, %% Kill disksup @@ -378,23 +355,23 @@ otp_5910(Config) when is_list(Config) -> %% Wait a little to make sure disksup has been restarted, %% then make sure the alarms are set once, but not twice - ?t:sleep(?t:seconds(1)), + ct:sleep({seconds,1}), Data3 = disksup:get_disk_data(), Alarms2 = get_alarms(), if length(Alarms2)==length(Alarms) -> ok; true -> dump_info(), - ?t:fail({bad_alarms,Threshold,Data3,Alarms,Alarms2}) + ct:fail({bad_alarms,Threshold,Data3,Alarms,Alarms2}) end, %% Stop OS_Mon and make sure all disksup alarms are cleared ok = application:stop(os_mon), - ?t:sleep(?t:seconds(1)), + ct:sleep({seconds,1}), Alarms3 = get_alarms(), case get_alarms() of [] -> ok; - _ -> ?t:fail({alarms_not_cleared, Alarms3}) + _ -> ct:fail({alarms_not_cleared, Alarms3}) end, %% Reset threshold and restart OS_Mon @@ -403,8 +380,7 @@ otp_5910(Config) when is_list(Config) -> ok = application:start(os_mon), ok. -posix_only(suite) -> []; -posix_only(doc) -> ["Test disksup_posix_only option"]; +%% Test disksup_posix_only option posix_only(Config) when is_list(Config) -> %% Set option and restart disksup ok = application:set_env(os_mon, disksup_posix_only, true), diff --git a/lib/os_mon/test/memsup_SUITE.erl b/lib/os_mon/test/memsup_SUITE.erl index 904c9b95b0..ed78b1ab1c 100644 --- a/lib/os_mon/test/memsup_SUITE.erl +++ b/lib/os_mon/test/memsup_SUITE.erl @@ -21,7 +21,7 @@ -include_lib("common_test/include/ct.hrl"). %% Test server specific exports --export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]). +-export([all/0, suite/0]). -export([init_per_suite/1, end_per_suite/1]). -export([init_per_testcase/2, end_per_testcase/2]). @@ -30,384 +30,362 @@ -export([config/1, timeout/1, unavailable/1, port/1]). -export([otp_5910/1]). -%% Default timetrap timeout (set in init_per_testcase) --define(default_timeout, ?t:minutes(1)). - init_per_suite(Config) when is_list(Config) -> - ?line ok = application:start(os_mon), + ok = application:start(os_mon), Config. end_per_suite(Config) when is_list(Config) -> - ?line ok = application:stop(os_mon), + ok = application:stop(os_mon), Config. init_per_testcase(_Case, Config) -> - Dog = ?t:timetrap(?default_timeout), - [{watchdog,Dog} | Config]. - -end_per_testcase(_Case, Config) -> - Dog = ?config(watchdog, Config), - ?t:timetrap_cancel(Dog), Config. -suite() -> [{ct_hooks,[ts_install_cth]}]. +end_per_testcase(_Case, _Config) -> + ok. + +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> All = case test_server:os_type() of - {unix, sunos} -> - [api, alarm1, alarm2, process, config, timeout, - unavailable, port]; - {unix, linux} -> - [api, alarm1, alarm2, process, timeout]; - _OS -> [api, alarm1, alarm2, process] - end, + {unix, sunos} -> + [api, alarm1, alarm2, process, config, timeout, + unavailable, port]; + {unix, linux} -> + [api, alarm1, alarm2, process, timeout]; + _OS -> [api, alarm1, alarm2, process] + end, Bugs = [otp_5910], All ++ Bugs. -groups() -> - []. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - -api(suite) -> - []; -api(doc) -> - ["Test of API functions"]; +%% Test of API functions api(Config) when is_list(Config) -> %% get_memory_data() - ?line RegMemData = memsup:get_memory_data(), + RegMemData = memsup:get_memory_data(), case RegMemData of - {TotMem, AllBytes, {Pid, PidBytes}} when is_integer(TotMem), - is_integer(AllBytes), - is_pid(Pid), - is_integer(PidBytes) -> - ok; - {0, 0, _WorstPid} -> - ?line ?t:fail(first_data_collection_failed); - _ -> - ?line ?t:fail({bad_return, RegMemData}) + {TotMem, AllBytes, {Pid, PidBytes}} when is_integer(TotMem), + is_integer(AllBytes), + is_pid(Pid), + is_integer(PidBytes) -> + ok; + {0, 0, _WorstPid} -> + ct:fail(first_data_collection_failed); + _ -> + ct:fail({bad_return, RegMemData}) end, %% get_system_memory_data() - ?line ExtMemData = memsup:get_system_memory_data(), - Tags = [ total_memory, - free_memory, - system_total_memory, - largest_free, - number_of_free, - free_swap, - total_swap, - cached_memory, - buffered_memory, - shared_memory], - - ?line true = lists:all(fun({Tag,Value}) when is_atom(Tag), - is_integer(Value) -> - lists:member(Tag, Tags); - (_) -> - false - end, - ExtMemData), + ExtMemData = memsup:get_system_memory_data(), + Tags = [total_memory, + free_memory, + system_total_memory, + largest_free, + number_of_free, + free_swap, + total_swap, + cached_memory, + buffered_memory, + shared_memory], + + true = lists:all(fun({Tag,Value}) when is_atom(Tag), + is_integer(Value) -> + lists:member(Tag, Tags); + (_) -> + false + end, ExtMemData), %% get_os_wordsize() - ?line ok = case memsup:get_os_wordsize() of - 32 -> ok; - 64 -> ok; - unsupported_os -> ok; - _ -> error - end, + ok = case memsup:get_os_wordsize() of + 32 -> ok; + 64 -> ok; + unsupported_os -> ok; + _ -> error + end, %% get_check_interval() - ?line 60000 = memsup:get_check_interval(), + 60000 = memsup:get_check_interval(), %% set_check_interval(Minutes) - ?line ok = memsup:set_check_interval(2), - ?line 120000 = memsup:get_check_interval(), - ?line {'EXIT',{badarg,_}} = - (catch memsup:set_check_interval(0.2)), - ?line 120000 = memsup:get_check_interval(), - ?line ok = memsup:set_check_interval(1), + ok = memsup:set_check_interval(2), + 120000 = memsup:get_check_interval(), + {'EXIT',{badarg,_}} = + (catch memsup:set_check_interval(0.2)), + 120000 = memsup:get_check_interval(), + ok = memsup:set_check_interval(1), %% get_procmem_high_watermark() - ?line 5 = memsup:get_procmem_high_watermark(), + 5 = memsup:get_procmem_high_watermark(), %% set_procmem_high_watermark() - ?line ok = memsup:set_procmem_high_watermark(0.1), - ?line 10 = memsup:get_procmem_high_watermark(), - ?line {'EXIT',{badarg,_}} = - (catch memsup:set_procmem_high_watermark(-0.1)), - ?line 10 = memsup:get_procmem_high_watermark(), - ?line ok = memsup:set_procmem_high_watermark(0.05), + ok = memsup:set_procmem_high_watermark(0.1), + 10 = memsup:get_procmem_high_watermark(), + {'EXIT',{badarg,_}} = + (catch memsup:set_procmem_high_watermark(-0.1)), + 10 = memsup:get_procmem_high_watermark(), + ok = memsup:set_procmem_high_watermark(0.05), %% get_sysmem_high_watermark() - ?line 80 = memsup:get_sysmem_high_watermark(), + 80 = memsup:get_sysmem_high_watermark(), %% set_sysmem_high_watermark() - ?line ok = memsup:set_sysmem_high_watermark(0.9), - ?line 90 = memsup:get_sysmem_high_watermark(), - ?line {'EXIT',{badarg,_}} = - (catch memsup:set_sysmem_high_watermark(-0.9)), - ?line 90 = memsup:get_sysmem_high_watermark(), - ?line ok = memsup:set_sysmem_high_watermark(0.8), + ok = memsup:set_sysmem_high_watermark(0.9), + 90 = memsup:get_sysmem_high_watermark(), + {'EXIT',{badarg,_}} = + (catch memsup:set_sysmem_high_watermark(-0.9)), + 90 = memsup:get_sysmem_high_watermark(), + ok = memsup:set_sysmem_high_watermark(0.8), %% get|set_helper_timeout - ?line 30 = memsup:get_helper_timeout(), - ?line ok = memsup:set_helper_timeout(29), - ?line 29 = memsup:get_helper_timeout(), - ?line {'EXIT',{badarg,_}} = (catch memsup:set_helper_timeout(31.0)), - ?line 29 = memsup:get_helper_timeout(), + 30 = memsup:get_helper_timeout(), + ok = memsup:set_helper_timeout(29), + 29 = memsup:get_helper_timeout(), + {'EXIT',{badarg,_}} = (catch memsup:set_helper_timeout(31.0)), + 29 = memsup:get_helper_timeout(), ok. %%---------------------------------------------------------------------- %% NOTE: The test case is a bit weak as it will fail if the memory %% usage changes too much during its course. %%---------------------------------------------------------------------- -alarm1(suite) -> - []; -alarm1(doc) -> - ["Test alarms when memsup_system_only==false"]; + +%% Test alarms when memsup_system_only==false alarm1(Config) when is_list(Config) -> %% If system memory usage is too high, the testcase cannot %% be run correctly - ?line {Total, Alloc, {_Pid,_PidAlloc}} = memsup:get_memory_data(), + {Total, Alloc, {_Pid,_PidAlloc}} = memsup:get_memory_data(), io:format("alarm1: Total: ~p, Alloc: ~p~n", [Total, Alloc]), - ?line SysUsage = Alloc/Total, + SysUsage = Alloc/Total, if - SysUsage>0.99 -> - {skip, sys_mem_too_high}; - true -> - alarm1(Config, SysUsage) + SysUsage > 0.99 -> + {skip, sys_mem_too_high}; + true -> + alarm1(Config, SysUsage) end. alarm1(_Config, SysUsage) -> %% Set a long memory check interval, we will force memory checks %% instead - ?line ok = memsup:set_check_interval(60), + ok = memsup:set_check_interval(60), %% Check thresholds - ?line SysThreshold = (memsup:get_sysmem_high_watermark()/100), - ?line ProcThreshold = (memsup:get_procmem_high_watermark()/100), + SysThreshold = (memsup:get_sysmem_high_watermark()/100), + ProcThreshold = (memsup:get_procmem_high_watermark()/100), %% Check if a system alarm already should be set or not SysP = if - SysUsage>SysThreshold -> true; - SysUsage=<SysThreshold -> false - end, + SysUsage>SysThreshold -> true; + SysUsage=<SysThreshold -> false + end, %% If system memory is higher than threshold, make sure the system %% alarm is set. Otherwise, make sure it is not set case alarm_set(system_memory_high_watermark) of - {true, []} when SysP -> - ok; - false when not SysP -> - ok; - _ -> - ?line ?t:fail({sys_alarm, SysUsage, SysThreshold}) + {true, []} when SysP -> + ok; + false when not SysP -> + ok; + _ -> + ct:fail({sys_alarm, SysUsage, SysThreshold}) end, %% Lower/raise the threshold to clear/set the alarm NewSysThreshold = if - SysP -> - Value = 1.1*SysUsage, - if - Value > 0.99 -> 0.99; - true -> Value - end; - not SysP -> 0.9*SysUsage - end, + SysP -> + Value = 1.1*SysUsage, + if + Value > 0.99 -> 0.99; + true -> Value + end; + not SysP -> 0.9*SysUsage + end, - ?line ok = memsup:set_sysmem_high_watermark(NewSysThreshold), + ok = memsup:set_sysmem_high_watermark(NewSysThreshold), %% Initiate and wait for a new data collection - ?line ok = force_collection(), + ok = force_collection(), %% Make sure the alarm is cleared/set - ?t:sleep(?t:seconds(5)), + ct:sleep({seconds,5}), case alarm_set(system_memory_high_watermark) of - {true, []} when not SysP -> - ok; - false when SysP -> - ok; - _ -> - ?line ?t:fail({sys_alarm, SysUsage, NewSysThreshold}) + {true, []} when not SysP -> + ok; + false when SysP -> + ok; + _ -> + ct:fail({sys_alarm, SysUsage, NewSysThreshold}) end, %% Reset the threshold to set/clear the alarm again - ?line ok = memsup:set_sysmem_high_watermark(SysThreshold), - ?line ok = force_collection(), - ?t:sleep(?t:seconds(1)), + ok = memsup:set_sysmem_high_watermark(SysThreshold), + ok = force_collection(), + ct:sleep({seconds,1}), case alarm_set(system_memory_high_watermark) of - {true, []} when SysP -> - ok; - false when not SysP -> - ok; - _ -> - ?line ?t:fail({sys_alarm, SysUsage, SysThreshold}) + {true, []} when SysP -> + ok; + false when not SysP -> + ok; + _ -> + ct:fail({sys_alarm, SysUsage, SysThreshold}) end, %% Check memory usage - ?line {Total2, _, {WorstPid, PidAlloc}} = memsup:get_memory_data(), + {Total2, _, {WorstPid, PidAlloc}} = memsup:get_memory_data(), %% Check if a process alarm already should be set or not PidUsage = PidAlloc/Total2, ProcP = if - PidUsage>ProcThreshold -> true; - PidUsage=<ProcThreshold -> false - end, + PidUsage>ProcThreshold -> true; + PidUsage=<ProcThreshold -> false + end, %% Make sure the process alarm is set/not set accordingly case alarm_set(process_memory_high_watermark) of - {true, WorstPid} when ProcP -> - ok; - false when not ProcP -> - ok; - {true, BadPid1} when ProcP -> - ?line ?t:fail({proc_alarm, WorstPid, BadPid1}); - _ -> - ?line ?t:fail({proc_alarm, PidUsage, ProcThreshold}) + {true, WorstPid} when ProcP -> + ok; + false when not ProcP -> + ok; + {true, BadPid1} when ProcP -> + ct:fail({proc_alarm, WorstPid, BadPid1}); + _ -> + ct:fail({proc_alarm, PidUsage, ProcThreshold}) end, %% Lower/raise the threshold to clear/set the alarm NewProcThreshold = if - ProcP -> 1.1*PidUsage; - not ProcP -> 0.9*PidUsage - end, - ?line ok = memsup:set_procmem_high_watermark(NewProcThreshold), - ?line ok = force_collection(), - ?t:sleep(?t:seconds(1)), + ProcP -> 1.1*PidUsage; + not ProcP -> 0.9*PidUsage + end, + ok = memsup:set_procmem_high_watermark(NewProcThreshold), + ok = force_collection(), + ct:sleep({seconds,1}), case alarm_set(process_memory_high_watermark) of - {true, WorstPid} when not ProcP -> - ok; - false when ProcP -> - ok; - {true, BadPid2} when not ProcP -> - ?line test_server:fail({proc_alarm, WorstPid, BadPid2}); - _ -> - ?line ?t:fail({proc_alarm, PidUsage, ProcThreshold}) + {true, WorstPid} when not ProcP -> + ok; + false when ProcP -> + ok; + {true, BadPid2} when not ProcP -> + ct:fail({proc_alarm, WorstPid, BadPid2}); + _ -> + ct:fail({proc_alarm, PidUsage, ProcThreshold}) end, %% Reset the threshold to clear/set the alarm - ?line ok = memsup:set_procmem_high_watermark(ProcThreshold), - ?line ok = force_collection(), - ?t:sleep(?t:seconds(1)), + ok = memsup:set_procmem_high_watermark(ProcThreshold), + ok = force_collection(), + ct:sleep({seconds,1}), case alarm_set(process_memory_high_watermark) of - {true, WorstPid} when ProcP -> - ok; - false when not ProcP -> - ok; - {true, BadPid3} when ProcP -> - ?line test_server:fail({proc_alarm, WorstPid, BadPid3}); - _ -> - ?line ?t:fail({proc_alarm, PidUsage, ProcThreshold}) + {true, WorstPid} when ProcP -> + ok; + false when not ProcP -> + ok; + {true, BadPid3} when ProcP -> + ct:fail({proc_alarm, WorstPid, BadPid3}); + _ -> + ct:fail({proc_alarm, PidUsage, ProcThreshold}) end, %% Reset memory check interval - ?line ok = memsup:set_check_interval(1), + ok = memsup:set_check_interval(1), ok. -alarm2(suite) -> - []; -alarm2(doc) -> - ["Test alarms when memsup_system_only==true"]; +%% Test alarms when memsup_system_only==true alarm2(Config) when is_list(Config) -> %% If system memory usage is too high, the testcase cannot %% be run correctly - ?line {Total, Alloc, {_Pid,_PidAlloc}} = memsup:get_memory_data(), - ?line SysUsage = Alloc/Total, + {Total, Alloc, {_Pid,_PidAlloc}} = memsup:get_memory_data(), + SysUsage = Alloc/Total, if - SysUsage>0.99 -> - {skip, sys_mem_too_high}; - true -> - alarm2(Config, SysUsage) + SysUsage>0.99 -> + {skip, sys_mem_too_high}; + true -> + alarm2(Config, SysUsage) end. alarm2(_Config, _SysUsage) -> %% Change memsup_system_only and restart memsup - ?line ok = application:set_env(os_mon, memsup_system_only, true), - ?line ok = supervisor:terminate_child(os_mon_sup, memsup), - ?line {ok, _Memsup1} = supervisor:restart_child(os_mon_sup, memsup), + ok = application:set_env(os_mon, memsup_system_only, true), + ok = supervisor:terminate_child(os_mon_sup, memsup), + {ok, _Memsup1} = supervisor:restart_child(os_mon_sup, memsup), %% Set a long memory check interval, we will force memory checks %% instead - ?line ok = memsup:set_check_interval(60), + ok = memsup:set_check_interval(60), %% Check data and thresholds - ?line {Total, Alloc, undefined} = memsup:get_memory_data(), - ?line SysThreshold = (memsup:get_sysmem_high_watermark()/100), - ?line true = is_integer(memsup:get_procmem_high_watermark()), + {Total, Alloc, undefined} = memsup:get_memory_data(), + SysThreshold = (memsup:get_sysmem_high_watermark()/100), + true = is_integer(memsup:get_procmem_high_watermark()), %% Check if a system alarm already should be set or not - ?line SysUsage = Alloc/Total, + SysUsage = Alloc/Total, SysP = if - SysUsage>SysThreshold -> true; - SysUsage=<SysThreshold -> false - end, + SysUsage>SysThreshold -> true; + SysUsage=<SysThreshold -> false + end, %% If system memory is higher than threshold, make sure the system %% alarm is set. Otherwise, make sure it is not set case alarm_set(system_memory_high_watermark) of - {true, []} when SysP -> - ok; - false when not SysP -> - ok; - _ -> - ?line ?t:fail({sys_alarm, SysUsage, SysThreshold}) + {true, []} when SysP -> + ok; + false when not SysP -> + ok; + _ -> + ct:fail({sys_alarm, SysUsage, SysThreshold}) end, %% Lower/raise the threshold to clear/set the alarm NewSysThreshold = if - SysP -> - Value = 1.1*SysUsage, - if - Value > 0.99 -> 0.99; - true -> Value - end; - not SysP -> 0.9*SysUsage - end, + SysP -> + Value = 1.1*SysUsage, + if + Value > 0.99 -> 0.99; + true -> Value + end; + not SysP -> 0.9*SysUsage + end, - ?line ok = memsup:set_sysmem_high_watermark(NewSysThreshold), + ok = memsup:set_sysmem_high_watermark(NewSysThreshold), %% Initiate and wait for a new data collection - ?line ok = force_collection(), + ok = force_collection(), %% Make sure the alarm is cleared/set - ?t:sleep(?t:seconds(1)), + ct:sleep({seconds,1}), case alarm_set(system_memory_high_watermark) of - {true, []} when not SysP -> - ok; - false when SysP -> - ok; - _ -> - ?line ?t:fail({sys_alarm, SysUsage, NewSysThreshold}) + {true, []} when not SysP -> + ok; + false when SysP -> + ok; + _ -> + ct:fail({sys_alarm, SysUsage, NewSysThreshold}) end, %% Reset the threshold to set/clear the alarm again - ?line ok = memsup:set_sysmem_high_watermark(SysThreshold), - ?line ok = force_collection(), - ?t:sleep(?t:seconds(1)), + ok = memsup:set_sysmem_high_watermark(SysThreshold), + ok = force_collection(), + ct:sleep({seconds,1}), case alarm_set(system_memory_high_watermark) of - {true, []} when SysP -> - ok; - false when not SysP -> - ok; - _ -> - ?line ?t:fail({sys_alarm, SysUsage, SysThreshold}) + {true, []} when SysP -> + ok; + false when not SysP -> + ok; + _ -> + ct:fail({sys_alarm, SysUsage, SysThreshold}) end, %% Reset memsup_system_only and restart memsup %% (memory check interval is then automatically reset) - ?line ok = application:set_env(os_mon, memsup_system_only, false), - ?line ok = supervisor:terminate_child(os_mon_sup, memsup), - ?line {ok, _Memsup2} = supervisor:restart_child(os_mon_sup, memsup), + ok = application:set_env(os_mon, memsup_system_only, false), + ok = supervisor:terminate_child(os_mon_sup, memsup), + {ok, _Memsup2} = supervisor:restart_child(os_mon_sup, memsup), ok. @@ -420,39 +398,36 @@ alarm_set(Alarm, [_|T]) -> alarm_set(_Alarm, []) -> false. -process(suite) -> - []; -process(doc) -> - ["Make sure memsup discovers a process grown very large"]; +%% Make sure memsup discovers a process grown very large process(Config) when is_list(Config) -> %% Set a long memory check interval, we will force memory checks %% instead - ?line ok = memsup:set_check_interval(60), + ok = memsup:set_check_interval(60), %% Collect data MemData = memsup:get_memory_data(), io:format("process: memsup:get_memory_data() = ~p~n", [MemData]), - ?line {_Total,_Free,{_,Bytes}} = MemData, + {_Total,_Free,{_,Bytes}} = MemData, %% Start a new process larger than Worst - ?line WorsePid = spawn(fun() -> new_hog(Bytes) end), - ?t:sleep(?t:seconds(1)), + WorsePid = spawn(fun() -> new_hog(Bytes) end), + ct:sleep({seconds,1}), %% Initiate and wait for a new data collection - ?line ok = force_collection(), + ok = force_collection(), %% Check that get_memory_data() returns updated result - ?line case memsup:get_memory_data() of - {_, _, {WorsePid, _MoreBytes}} -> - ok; - {_, _, BadWorst} -> - ?line ?t:fail({worst_pid, BadWorst}) - end, + case memsup:get_memory_data() of + {_, _, {WorsePid, _MoreBytes}} -> + ok; + {_, _, BadWorst} -> + ct:fail({worst_pid, BadWorst}) + end, %% Reset memory check interval - ?line exit(WorsePid, done), - ?line ok = memsup:set_check_interval(1), + exit(WorsePid, done), + ok = memsup:set_check_interval(1), ok. new_hog(Bytes) -> @@ -463,110 +438,101 @@ new_hog(Bytes) -> new_hog_1(List) -> receive - _Any -> exit(List) + _Any -> exit(List) end. -config(suite) -> - []; -config(doc) -> - ["Test configuration"]; +%% Test configuration config(Config) when is_list(Config) -> %% Change configuration parameters and make sure change is reflected %% when memsup is restarted - ?line ok = application:set_env(os_mon, memory_check_interval, 2), - ?line ok = - application:set_env(os_mon, system_memory_high_watermark, 0.9), - ?line ok = - application:set_env(os_mon, process_memory_high_watermark, 0.1), - ?line ok = application:set_env(os_mon, memsup_helper_timeout, 35), - ?line ok = application:set_env(os_mon, memsup_system_only, true), - - ?line ok = supervisor:terminate_child(os_mon_sup, memsup), - ?line {ok, _Child1} = supervisor:restart_child(os_mon_sup, memsup), - - ?line 120000 = memsup:get_check_interval(), - ?line 90 = memsup:get_sysmem_high_watermark(), - ?line 10 = memsup:get_procmem_high_watermark(), - ?line 35 = memsup:get_helper_timeout(), + ok = application:set_env(os_mon, memory_check_interval, 2), + ok = + application:set_env(os_mon, system_memory_high_watermark, 0.9), + ok = + application:set_env(os_mon, process_memory_high_watermark, 0.1), + ok = application:set_env(os_mon, memsup_helper_timeout, 35), + ok = application:set_env(os_mon, memsup_system_only, true), + + ok = supervisor:terminate_child(os_mon_sup, memsup), + {ok, _Child1} = supervisor:restart_child(os_mon_sup, memsup), + + 120000 = memsup:get_check_interval(), + 90 = memsup:get_sysmem_high_watermark(), + 10 = memsup:get_procmem_high_watermark(), + 35 = memsup:get_helper_timeout(), %% Also try this with bad parameter values, should be ignored - ?line ok = application:set_env(os_mon, memory_check_interval, 0.2), - ?line ok = - application:set_env(os_mon, system_memory_high_watermark, -0.9), - ?line ok = - application:set_env(os_mon, process_memory_high_watermark,-0.1), - ?line ok = application:set_env(os_mon, memsup_helper_timeout, 0.35), - ?line ok = application:set_env(os_mon, memsup_system_only, arne), - - ?line ok = supervisor:terminate_child(os_mon_sup, memsup), - ?line {ok, _Child2} = supervisor:restart_child(os_mon_sup, memsup), - - ?line 60000 = memsup:get_check_interval(), - ?line 80 = memsup:get_sysmem_high_watermark(), - ?line 5 = memsup:get_procmem_high_watermark(), - ?line 30 = memsup:get_helper_timeout(), + ok = application:set_env(os_mon, memory_check_interval, 0.2), + ok = + application:set_env(os_mon, system_memory_high_watermark, -0.9), + ok = + application:set_env(os_mon, process_memory_high_watermark,-0.1), + ok = application:set_env(os_mon, memsup_helper_timeout, 0.35), + ok = application:set_env(os_mon, memsup_system_only, arne), + + ok = supervisor:terminate_child(os_mon_sup, memsup), + {ok, _Child2} = supervisor:restart_child(os_mon_sup, memsup), + + 60000 = memsup:get_check_interval(), + 80 = memsup:get_sysmem_high_watermark(), + 5 = memsup:get_procmem_high_watermark(), + 30 = memsup:get_helper_timeout(), %% Reset configuration parameters - ?line ok = application:set_env(os_mon, memory_check_interval, 1), - ?line ok = - application:set_env(os_mon, system_memory_high_watermark, 0.8), - ?line ok = - application:set_env(os_mon, process_memory_high_watermark,0.05), - ?line ok = application:set_env(os_mon, memsup_helper_timeout, 30), - ?line ok = application:set_env(os_mon, memsup_system_only, false), + ok = application:set_env(os_mon, memory_check_interval, 1), + ok = + application:set_env(os_mon, system_memory_high_watermark, 0.8), + ok = + application:set_env(os_mon, process_memory_high_watermark,0.05), + ok = application:set_env(os_mon, memsup_helper_timeout, 30), + ok = application:set_env(os_mon, memsup_system_only, false), ok. -unavailable(suite) -> - []; -unavailable(doc) -> - ["Test correct behaviour when service is unavailable"]; +%% Test correct behaviour when service is unavailable unavailable(Config) when is_list(Config) -> %% Close memsup - ?line ok = application:set_env(os_mon, start_memsup, false), - ?line ok = supervisor:terminate_child(os_mon_sup, memsup), + ok = application:set_env(os_mon, start_memsup, false), + ok = supervisor:terminate_child(os_mon_sup, memsup), %% Make sure all API functions return their dummy values - ?line {0,0,{_Pid,0}} = memsup:get_memory_data(), - ?line ok = application:set_env(os_mon, memsup_system_only, true), - ?line {0,0,undefined} = memsup:get_memory_data(), - ?line ok = application:set_env(os_mon, memsup_system_only, false), - ?line [] = memsup:get_system_memory_data(), - ?line 0 = memsup:get_os_wordsize(), - ?line 60000 = memsup:get_check_interval(), - ?line ok = memsup:set_check_interval(2), - ?line 5 = memsup:get_procmem_high_watermark(), - ?line ok = memsup:set_procmem_high_watermark(0.10), - ?line 80 = memsup:get_sysmem_high_watermark(), - ?line ok = memsup:set_sysmem_high_watermark(0.90), - ?line 30 = memsup:get_helper_timeout(), - ?line ok = memsup:set_helper_timeout(35), + {0,0,{_Pid,0}} = memsup:get_memory_data(), + ok = application:set_env(os_mon, memsup_system_only, true), + {0,0,undefined} = memsup:get_memory_data(), + ok = application:set_env(os_mon, memsup_system_only, false), + [] = memsup:get_system_memory_data(), + 0 = memsup:get_os_wordsize(), + 60000 = memsup:get_check_interval(), + ok = memsup:set_check_interval(2), + 5 = memsup:get_procmem_high_watermark(), + ok = memsup:set_procmem_high_watermark(0.10), + 80 = memsup:get_sysmem_high_watermark(), + ok = memsup:set_sysmem_high_watermark(0.90), + 30 = memsup:get_helper_timeout(), + ok = memsup:set_helper_timeout(35), %% Start memsup again, - ?line ok = application:set_env(os_mon, start_memsup, true), - ?line {ok, _Child} = supervisor:restart_child(os_mon_sup, memsup), + ok = application:set_env(os_mon, start_memsup, true), + {ok, _Child} = supervisor:restart_child(os_mon_sup, memsup), ok. -timeout(suite) -> - []; -timeout(doc) -> - ["Test stability of memsup when data collection times out"]; +%% Test stability of memsup when data collection times out timeout(Config) when is_list(Config) -> %% Set a long memory check interval and memsup_helper timeout, %% we will force memory checks instead and fake timeouts - ?line ok = memsup:set_check_interval(60), - ?line ok = memsup:set_helper_timeout(3600), + ok = memsup:set_check_interval(60), + ok = memsup:set_helper_timeout(3600), %% Provoke a timeout during memory collection - ?line memsup ! time_to_collect, - ?line memsup ! reg_collection_timeout, + memsup ! time_to_collect, + memsup ! reg_collection_timeout, %% Not much we can check though, except that memsup is still running - ?line {_,_,_} = memsup:get_memory_data(), + {_,_,_} = memsup:get_memory_data(), %% Provoke a timeout during extensive memory collection %% We fake a gen_server:call/2 to be able to send a timeout message @@ -574,140 +540,133 @@ timeout(Config) when is_list(Config) -> %% Linux should be handled the same way as solaris. -% TimeoutMsg = case ?t:os_type() of -% {unix, sunos} -> ext_collection_timeout; -% {unix, linux} -> reg_collection_timeout -% end, + % TimeoutMsg = case ?t:os_type() of + % {unix, sunos} -> ext_collection_timeout; + % {unix, linux} -> reg_collection_timeout + % end, TimeoutMsg = ext_collection_timeout, - ?line Pid = whereis(memsup), - ?line Mref = erlang:monitor(process, Pid), - ?line Pid ! {'$gen_call', {self(), Mref}, get_system_memory_data}, - ?line Pid ! TimeoutMsg, + Pid = whereis(memsup), + Mref = erlang:monitor(process, Pid), + Pid ! {'$gen_call', {self(), Mref}, get_system_memory_data}, + Pid ! TimeoutMsg, receive - {Mref, []} -> - erlang:demonitor(Mref), - ?line ok; - {Mref, Res} -> - erlang:demonitor(Mref), - ?line ?t:fail({unexpected_result, Res}); - {'DOWN', Mref, _, _, _} -> - ?line ?t:fail(no_result) + {Mref, []} -> + erlang:demonitor(Mref), + ok; + {Mref, Res} -> + erlang:demonitor(Mref), + ct:fail({unexpected_result, Res}); + {'DOWN', Mref, _, _, _} -> + ct:fail(no_result) end, %% Reset memory check interval and memsup_helper timeout - ?line ok = memsup:set_check_interval(1), - ?line ok = memsup:set_helper_timeout(30), - ?line memsup ! time_to_collect, + ok = memsup:set_check_interval(1), + ok = memsup:set_helper_timeout(30), + memsup ! time_to_collect, - ?line [_|_] = memsup:get_system_memory_data(), + [_|_] = memsup:get_system_memory_data(), ok. -port(suite) -> - []; -port(doc) -> - ["Test that memsup handles a terminating port program"]; +%% Test that memsup handles a terminating port program port(Config) when is_list(Config) -> - ?line Str = os:cmd("ps -e | grep '[m]emsup'"), + Str = os:cmd("ps -e | grep '[m]emsup'"), case io_lib:fread("~s", Str) of - {ok, [Pid], _Rest} -> - - %% Monitor memsup - ?line MonRef = erlang:monitor(process, memsup), - ?line {Total1,_Alloc1,_Worst1} = memsup:get_memory_data(), - ?line true = Total1>0, - - %% Kill the port program - case os:cmd("kill -9 " ++ Pid) of - [] -> - - %% memsup should now terminate - receive - {'DOWN', MonRef, _, _, {port_died, _Reason}} -> - ok; - {'DOWN', MonRef, _, _, Reason} -> - ?line ?t:fail({unexpected_exit_reason, Reason}) - after - 3000 -> - ?line ?t:fail(still_alive) - end, - - %% Give os_mon_sup time to restart memsup - ?t:sleep(?t:seconds(3)), - ?line {Total2,_Alloc2,_Worst2} = - memsup:get_memory_data(), - ?line true = Total2>0, - - ok; - - Line -> - erlang:demonitor(MonRef), - {skip, {not_killed, Line}} - end; - _ -> - {skip, {os_pid_not_found, Str}} + {ok, [Pid], _Rest} -> + + %% Monitor memsup + MonRef = erlang:monitor(process, memsup), + {Total1,_Alloc1,_Worst1} = memsup:get_memory_data(), + true = Total1>0, + + %% Kill the port program + case os:cmd("kill -9 " ++ Pid) of + [] -> + + %% memsup should now terminate + receive + {'DOWN', MonRef, _, _, {port_died, _Reason}} -> + ok; + {'DOWN', MonRef, _, _, Reason} -> + ct:fail({unexpected_exit_reason, Reason}) + after + 3000 -> + ct:fail(still_alive) + end, + + %% Give os_mon_sup time to restart memsup + ct:sleep({seconds,3}), + {Total2,_Alloc2,_Worst2} = + memsup:get_memory_data(), + true = Total2>0, + + ok; + + Line -> + erlang:demonitor(MonRef), + {skip, {not_killed, Line}} + end; + _ -> + {skip, {os_pid_not_found, Str}} end. -otp_5910(suite) -> - []; -otp_5910(doc) -> - ["Test that alarms are cleared and not set twice"]; +%% Test that alarms are cleared and not set twice otp_5910(Config) when is_list(Config) -> Alarms = - [system_memory_high_watermark, process_memory_high_watermark], + [system_memory_high_watermark, process_memory_high_watermark], %% Make sure memsup sets both alarms - ?line ok = application:set_env(os_mon, memory_check_interval, 60), - ?line ok = memsup:set_check_interval(60), - ?line SysThreshold = (memsup:get_sysmem_high_watermark()/100), - ?line ProcThreshold = (memsup:get_procmem_high_watermark()/100), + ok = application:set_env(os_mon, memory_check_interval, 60), + ok = memsup:set_check_interval(60), + SysThreshold = (memsup:get_sysmem_high_watermark()/100), + ProcThreshold = (memsup:get_procmem_high_watermark()/100), MemData = memsup:get_memory_data(), io:format("otp_5910: memsup:get_memory_data() = ~p~n", [MemData]), - ?line {Total, Alloc, {_Pid, _Bytes}} = MemData, - ?line Pid = spawn_opt(fun() -> - receive - die -> ok - end - end, [{min_heap_size, 1000}]), + {Total, Alloc, {_Pid, _Bytes}} = MemData, + Pid = spawn_opt(fun() -> + receive + die -> ok + end + end, [{min_heap_size, 1000}]), %% Create a process guaranteed to live, be constant and %% break memsup process limit - ?line {memory, Bytes} = erlang:process_info(Pid,memory), - ?line SysUsage = Alloc/Total, - ?line ProcUsage = Bytes/Total, + {memory, Bytes} = erlang:process_info(Pid,memory), + SysUsage = Alloc/Total, + ProcUsage = Bytes/Total, if - SysUsage>SysThreshold -> - ok; - SysUsage=<SysThreshold -> - ?line ok = application:set_env(os_mon, - sys_mem_high_watermark, - 0.5 * SysUsage), - ?line ok = memsup:set_sysmem_high_watermark(0.5 * SysUsage) + SysUsage>SysThreshold -> + ok; + SysUsage=<SysThreshold -> + ok = application:set_env(os_mon, + sys_mem_high_watermark, + 0.5 * SysUsage), + ok = memsup:set_sysmem_high_watermark(0.5 * SysUsage) end, if - ProcUsage>ProcThreshold -> - ok; - ProcUsage=<ProcThreshold -> - ?line ok = application:set_env(os_mon, - proc_mem_high_watermark, - 0.5 * ProcUsage), - ?line ok = memsup:set_procmem_high_watermark(0.5 *ProcUsage) + ProcUsage>ProcThreshold -> + ok; + ProcUsage=<ProcThreshold -> + ok = application:set_env(os_mon, + proc_mem_high_watermark, + 0.5 * ProcUsage), + ok = memsup:set_procmem_high_watermark(0.5 *ProcUsage) end, - ?line ok = force_collection(), - ?t:sleep(?t:seconds(1)), + ok = force_collection(), + ct:sleep({seconds,1}), lists:foreach(fun(AlarmId) -> - case alarm_set(AlarmId) of - {true, _} -> ok; - false -> - ?line ?t:fail({alarm_not_set, - AlarmId}) - end - end, - Alarms), + case alarm_set(AlarmId) of + {true, _} -> ok; + false -> + ct:fail({alarm_not_set, AlarmId}) + end + end, + Alarms), %% Kill guaranteed process... Pid ! die, @@ -715,42 +674,41 @@ otp_5910(Config) when is_list(Config) -> exit(whereis(memsup), faked_memsup_crash), %% Wait a little to make sure memsup has been restarted, %% then make sure the alarms are set once, but not twice - ?t:sleep(?t:seconds(1)), - ?line MemUsage = memsup:get_memory_data(), + ct:sleep({seconds,1}), + MemUsage = memsup:get_memory_data(), SetAlarms = alarm_handler:get_alarms(), case lists:foldl(fun(system_memory_high_watermark, {S, P}) -> - {S+1, P}; - (process_memory_high_watermark, {S, P}) -> - {S, P+1}; - (_AlarmId, Acc0) -> - Acc0 - end, - {0, 0}, - SetAlarms) of - {0, 0} -> - ok; - _ -> - ?line ?t:fail({bad_number_of_alarms, SetAlarms, MemUsage}) + {S+1, P}; + (process_memory_high_watermark, {S, P}) -> + {S, P+1}; + (_AlarmId, Acc0) -> + Acc0 + end, + {0, 0}, + SetAlarms) of + {0, 0} -> + ok; + _ -> + ct:fail({bad_number_of_alarms, SetAlarms, MemUsage}) end, %% Stop OS_Mon and make sure all memsup alarms are cleared - ?line ok = application:stop(os_mon), - ?t:sleep(?t:seconds(1)), + ok = application:stop(os_mon), + ct:sleep({seconds,1}), lists:foreach(fun(AlarmId) -> - case alarm_set(AlarmId) of - false -> ok; - {true, _} -> - ?line ?t:fail({alarm_is_set, AlarmId}) - end - end, - Alarms), + case alarm_set(AlarmId) of + false -> ok; + {true, _} -> + ct:fail({alarm_is_set, AlarmId}) + end + end, + Alarms), %% Reset configuration and restart OS_Mon - ?line ok = application:set_env(os_mon,memory_check_interval,1), - ?line ok = application:set_env(os_mon,sys_mem_high_watermark,0.8), - ?line ok = application:set_env(os_mon,proc_mem_high_watermark,0.05), - ?line ok = application:start(os_mon), - + ok = application:set_env(os_mon,memory_check_interval,1), + ok = application:set_env(os_mon,sys_mem_high_watermark,0.8), + ok = application:set_env(os_mon,proc_mem_high_watermark,0.05), + ok = application:start(os_mon), ok. %%---------------------------------------------------------------------- @@ -765,30 +723,30 @@ force_collection() -> force_collection(TimerRef) -> receive - {trace, _Pid, 'receive', {collected_sys, _Sys}} -> - erlang:cancel_timer(TimerRef), - erlang:trace(whereis(memsup), false, ['receive']), - flush(), - ok; - {trace, _Pid, 'receive', reg_collection_timeout} -> - erlang:cancel_timer(TimerRef), - erlang:trace(whereis(memsup), false, ['receive']), - flush(), - collection_timeout; - timout -> - erlang:trace(whereis(memsup), false, ['receive']), - flush(), - timeout; - _Msg -> - force_collection(TimerRef) + {trace, _Pid, 'receive', {collected_sys, _Sys}} -> + erlang:cancel_timer(TimerRef), + erlang:trace(whereis(memsup), false, ['receive']), + flush(), + ok; + {trace, _Pid, 'receive', reg_collection_timeout} -> + erlang:cancel_timer(TimerRef), + erlang:trace(whereis(memsup), false, ['receive']), + flush(), + collection_timeout; + timout -> + erlang:trace(whereis(memsup), false, ['receive']), + flush(), + timeout; + _Msg -> + force_collection(TimerRef) end. flush() -> receive - {trace, _, _, _} -> - flush(); - timeout -> - flush() + {trace, _, _, _} -> + flush(); + timeout -> + flush() after 0 -> - ok + ok end. diff --git a/lib/os_mon/test/os_mon_SUITE.erl b/lib/os_mon/test/os_mon_SUITE.erl index 0f7ae3a508..ace06796d6 100644 --- a/lib/os_mon/test/os_mon_SUITE.erl +++ b/lib/os_mon/test/os_mon_SUITE.erl @@ -21,92 +21,58 @@ -include_lib("common_test/include/ct.hrl"). %% Test server specific exports --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2]). --export([init_per_testcase/2, end_per_testcase/2]). +-export([all/0, suite/0]). %% Test cases -export([app_file/1, appup_file/1, config/1]). -%% Default timetrap timeout (set in init_per_testcase) --define(default_timeout, ?t:minutes(1)). - -init_per_testcase(_Case, Config) -> - Dog = test_server:timetrap(?default_timeout), - [{watchdog, Dog}|Config]. - -end_per_testcase(_Case, Config) -> - Dog = ?config(watchdog, Config), - test_server:timetrap_cancel(Dog), - ok. - -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> case test_server:os_type() of - {unix, sunos} -> [app_file, appup_file, config]; - _OS -> [app_file, appup_file] + {unix, sunos} -> [app_file, appup_file, config]; + _OS -> [app_file, appup_file] end. -groups() -> - []. - -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - - -app_file(suite) -> - []; -app_file(doc) -> - ["Testing .app file"]; +%% Testing .app file app_file(Config) when is_list(Config) -> - ?line ok = test_server:app_test(os_mon), + ok = test_server:app_test(os_mon), ok. appup_file(Config) when is_list(Config) -> ok = test_server:appup_test(os_mon). -config(suite) -> - []; -config(doc) -> - ["Test OS_Mon configuration"]; +%% Test OS_Mon configuration config(Config) when is_list(Config) -> IsReg = fun(Name) -> is_pid(whereis(Name)) end, IsNotReg = fun(Name) -> undefined == whereis(Name) end, - ?line ok = application:start(os_mon), - ?line true = lists:all(IsReg, [cpu_sup, disksup, memsup]), - ?line ok = application:stop(os_mon), - - ?line ok = application:set_env(os_mon, start_cpu_sup, false), - ?line ok = application:start(os_mon), - ?line true = lists:all(IsReg, [disksup, memsup]), - ?line true = IsNotReg(cpu_sup), - ?line ok = application:stop(os_mon), - ?line ok = application:set_env(os_mon, start_cpu_sup, true), - - ?line ok = application:set_env(os_mon, start_disksup, false), - ?line ok = application:start(os_mon), - ?line true = lists:all(IsReg, [cpu_sup, memsup]), - ?line true = IsNotReg(disksup), - ?line ok = application:stop(os_mon), - ?line ok = application:set_env(os_mon, start_disksup, true), - - ?line ok = application:set_env(os_mon, start_memsup, false), - ?line ok = application:start(os_mon), - ?line true = lists:all(IsReg, [cpu_sup, disksup]), - ?line true = IsNotReg(memsup), - ?line ok = application:stop(os_mon), - ?line ok = application:set_env(os_mon, start_memsup, true), + ok = application:start(os_mon), + true = lists:all(IsReg, [cpu_sup, disksup, memsup]), + ok = application:stop(os_mon), + + ok = application:set_env(os_mon, start_cpu_sup, false), + ok = application:start(os_mon), + true = lists:all(IsReg, [disksup, memsup]), + true = IsNotReg(cpu_sup), + ok = application:stop(os_mon), + ok = application:set_env(os_mon, start_cpu_sup, true), + + ok = application:set_env(os_mon, start_disksup, false), + ok = application:start(os_mon), + true = lists:all(IsReg, [cpu_sup, memsup]), + true = IsNotReg(disksup), + ok = application:stop(os_mon), + ok = application:set_env(os_mon, start_disksup, true), + + ok = application:set_env(os_mon, start_memsup, false), + ok = application:start(os_mon), + true = lists:all(IsReg, [cpu_sup, disksup]), + true = IsNotReg(memsup), + ok = application:stop(os_mon), + ok = application:set_env(os_mon, start_memsup, true), ok. diff --git a/lib/os_mon/test/os_mon_mib_SUITE.erl b/lib/os_mon/test/os_mon_mib_SUITE.erl index f8fb9e20fc..84487cd751 100644 --- a/lib/os_mon/test/os_mon_mib_SUITE.erl +++ b/lib/os_mon/test/os_mon_mib_SUITE.erl @@ -35,25 +35,23 @@ -include_lib("snmp/include/snmp_types.hrl"). % Test server specific exports --export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, - init_per_suite/1, end_per_suite/1, - init_per_testcase/2, end_per_testcase/2]). +-export([all/0, suite/0, groups/0, + init_per_suite/1, end_per_suite/1]). % Test cases must be exported. -export([update_load_table/1]). -export([get_mem_sys_mark/1, get_mem_proc_mark/1, get_disk_threshold/1, - get_load_table/1, get_disk_table/1, - real_snmp_request/1, load_unload/1]). + get_load_table/1, get_disk_table/1, + real_snmp_request/1, load_unload/1]). -export([sys_tot_mem/1, sys_used_mem/1, large_erl_process/1, - large_erl_process_mem/1, cpu_load/1, cpu_load5/1, cpu_load15/1, - os_wordsize/1, sys_tot_mem64/1, sys_used_mem64/1, - large_erl_process_mem64/1, disk_descr/1, disk_kbytes/1, - disk_capacity/1]). + large_erl_process_mem/1, cpu_load/1, cpu_load5/1, cpu_load15/1, + os_wordsize/1, sys_tot_mem64/1, sys_used_mem64/1, + large_erl_process_mem64/1, disk_descr/1, disk_kbytes/1, + disk_capacity/1]). --export([]). -export([otp_6351/1, otp_7441/1]). -define(TRAP_UDP, 5000). @@ -65,17 +63,11 @@ -define(MGR_PORT, 5001). %%--------------------------------------------------------------------- -init_per_testcase(_Case, Config) when is_list(Config) -> - Dog = test_server:timetrap(test_server:minutes(6)), - [{watchdog, Dog}|Config]. -end_per_testcase(_Case, Config) when is_list(Config) -> - Dog = ?config(watchdog, Config), - test_server:timetrap_cancel(Dog), - Config. - -suite() -> [{ct_hooks,[ts_install_cth]}, - {require, snmp_mgr_agent, snmp}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,6}}, + {require, snmp_mgr_agent, snmp}]. all() -> [load_unload, get_mem_sys_mark, get_mem_proc_mark, @@ -94,12 +86,6 @@ groups() -> {get_next_disk_table, [], [disk_descr, disk_kbytes, disk_capacity]}]. -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - %%--------------------------------------------------------------------- %%-------------------------------------------------------------------- @@ -112,9 +98,9 @@ end_per_group(_GroupName, Config) -> %% variable, but should NOT alter/remove any existing entries. %%-------------------------------------------------------------------- init_per_suite(Config) -> - ?line application:start(sasl), - ?line application:start(mnesia), - ?line application:start(os_mon), + application:start(sasl), + application:start(mnesia), + application:start(os_mon), ok = ct_snmp:start(Config,snmp_mgr_agent), @@ -130,7 +116,7 @@ init_per_suite(Config) -> %% Description: Cleanup after the whole suite %%-------------------------------------------------------------------- end_per_suite(Config) -> - PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), ConfDir = filename:join(PrivDir,"conf"), DbDir = filename:join(PrivDir,"db"), MgrDir = filename:join(PrivDir, "mgr"), @@ -152,92 +138,74 @@ end_per_suite(Config) -> %%--------------------------------------------------------------------- %% Test cases %%--------------------------------------------------------------------- -load_unload(doc) -> - ["Test to unload and the reload the OTP.mib "]; -load_unload(suite) -> []; + +%% Test to unload and the reload the OTP.mib load_unload(Config) when is_list(Config) -> - ?line os_mon_mib:unload(snmp_master_agent), - ?line os_mon_mib:load(snmp_master_agent), + os_mon_mib:unload(snmp_master_agent), + os_mon_mib:load(snmp_master_agent), ok. %%--------------------------------------------------------------------- -update_load_table(doc) -> - ["check os_mon_mib:update_load_table error handling"]; -update_load_table(suite) -> - []; +%% check os_mon_mib:update_load_table error handling update_load_table(Config) when is_list(Config) -> - ?line Node = start_node(), - ?line ok = rpc:call(Node,application,start,[sasl]), - ?line ok = rpc:call(Node,application,start,[os_mon]), - ?line ok = os_mon_mib:update_load_table(), - ?line rpc:call(Node,application,stop,[os_mon]), - ?line ok = os_mon_mib:update_load_table(), - ?line stop_node(Node), + Node = start_node(), + ok = rpc:call(Node,application,start,[sasl]), + ok = rpc:call(Node,application,start,[os_mon]), + ok = os_mon_mib:update_load_table(), + rpc:call(Node,application,stop,[os_mon]), + ok = os_mon_mib:update_load_table(), + stop_node(Node), ok. -otp_6351(doc) -> - ["like update_load_table, when memsup_system_only==true"]; -otp_6351(suite) -> - []; +%% like update_load_table, when memsup_system_only==true otp_6351(Config) when is_list(Config) -> - ?line Node = start_node(), - ?line ok = rpc:call(Node,application,start,[sasl]), - ?line ok = rpc:call(Node,application,load,[os_mon]), - ?line ok = rpc:call(Node,application,set_env, - [os_mon,memsup_system_only,true]), - ?line ok = rpc:call(Node,application,start,[os_mon]), - ?line Res = rpc:call(Node,os_mon_mib,get_load,[Node]), + Node = start_node(), + ok = rpc:call(Node,application,start,[sasl]), + ok = rpc:call(Node,application,load,[os_mon]), + ok = rpc:call(Node,application,set_env, + [os_mon,memsup_system_only,true]), + ok = rpc:call(Node,application,start,[os_mon]), + Res = rpc:call(Node,os_mon_mib,get_load,[Node]), if - is_tuple(Res), element(1, Res)==loadTable -> - ?line ok; - true -> - ?line ?t:fail(Res) + is_tuple(Res), element(1, Res)==loadTable -> + ok; + true -> + ct:fail(Res) end, - ?line rpc:call(Node,application,stop,[os_mon]), - ?line stop_node(Node), + rpc:call(Node,application,stop,[os_mon]), + stop_node(Node), ok. - - %%--------------------------------------------------------------------- -get_mem_sys_mark(doc) -> - ["Simulates a get call to test the instrumentation function " - "for the loadMemorySystemWatermark variable."]; -get_mem_sys_mark(suite) -> - []; +%% Simulates a get call to test the instrumentation function +%% for the loadMemorySystemWatermark variable. get_mem_sys_mark(Config) when is_list(Config) -> case os_mon_mib:mem_sys_mark(get) of - {value, SysMark} when is_integer(SysMark) -> - ok; - _ -> - ?line test_server:fail(sys_mark_value_not_integer) + {value, SysMark} when is_integer(SysMark) -> + ok; + _ -> + ct:fail(sys_mark_value_not_integer) end. %%--------------------------------------------------------------------- -get_mem_proc_mark(doc) -> - ["Simulates a get call to test the instrumentation function " - "for the loadMemoryErlProcWatermark variable."]; -get_mem_proc_mark(suite) -> - []; +%% Simulates a get call to test the instrumentation function +%% for the loadMemoryErlProcWatermark variable. get_mem_proc_mark(Config) when is_list(Config) -> case os_mon_mib:mem_proc_mark(get) of - {value, ProcMark} when is_integer(ProcMark) -> - ok; - _ -> - ?line test_server:fail(proc_mark_value_not_integer) + {value, ProcMark} when is_integer(ProcMark) -> + ok; + _ -> + ct:fail(proc_mark_value_not_integer) end. %%--------------------------------------------------------------------- -get_disk_threshold(doc) -> - ["Simulates a get call to test the instrumentation function " - "for the diskAlmostFullThreshold variable."]; -get_disk_threshold(suite) -> - []; +%% Simulates a get call to test the instrumentation function +%% for the diskAlmostFullThreshold variable. get_disk_threshold(Config) when is_list(Config) -> - case os_mon_mib:disk_threshold(get) of - {value, ProcMark} when is_integer(ProcMark) -> - ok; - _ -> - ?line test_server:fail(disk_threshold_value_not_integer) + case os_mon_mib:disk_threshold(get) of + {value, ProcMark} when is_integer(ProcMark) -> + ok; + _ -> + ct:fail(disk_threshold_value_not_integer) end. %%--------------------------------------------------------------------- @@ -247,11 +215,8 @@ get_disk_threshold(Config) when is_list(Config) -> %%% instrumentation functions directly as done in most test cases in %%% this test suite -get_load_table(doc) -> - ["Simulates get calls to test the instrumentation function " - "for the loadTable"]; -get_load_table(suite) -> - []; +%% Simulates get calls to test the instrumentation function +%% for the loadTable get_load_table(Config) when is_list(Config) -> NodeStr = atom_to_list(node()), @@ -259,376 +224,316 @@ get_load_table(Config) when is_list(Config) -> {_, _, {Pid, _}} = memsup:get_memory_data(), PidStr = lists:flatten(io_lib:format("~w", [Pid])), - ?line [{value, NodeStr},{value, PidStr}] = - os_mon_mib:load_table(get, [NodeLen | NodeStr], - [?loadErlNodeName, ?loadLargestErlProcess]), - - ?line Values = os_mon_mib:load_table(get, [NodeLen | NodeStr] , - [?loadSystemTotalMemory, - ?loadSystemUsedMemory, - ?loadLargestErlProcessUsedMemory, - ?loadCpuLoad, - ?loadCpuLoad5, - ?loadCpuLoad15, - ?loadOsWordsize, - ?loadSystemTotalMemory64, - ?loadSystemUsedMemory64, - ?loadLargestErlProcessUsedMemory64]), + [{value, NodeStr},{value, PidStr}] = + os_mon_mib:load_table(get, [NodeLen | NodeStr], + [?loadErlNodeName, ?loadLargestErlProcess]), + + Values = os_mon_mib:load_table(get, [NodeLen | NodeStr] , + [?loadSystemTotalMemory, + ?loadSystemUsedMemory, + ?loadLargestErlProcessUsedMemory, + ?loadCpuLoad, + ?loadCpuLoad5, + ?loadCpuLoad15, + ?loadOsWordsize, + ?loadSystemTotalMemory64, + ?loadSystemUsedMemory64, + ?loadLargestErlProcessUsedMemory64]), IsInt = fun({value, Val}) when is_integer(Val) -> - true; - (_) -> - false - end, + true; + (_) -> + false + end, NewValues = lists:filter(IsInt, Values), case length(NewValues) of - 10 -> - ok; - _ -> - ?line test_server:fail(value_not_integer) + 10 -> + ok; + _ -> + ct:fail(value_not_integer) end, - ?line [{noValue,noSuchInstance}, {noValue,noSuchInstance}, - {noValue,noSuchInstance}, {noValue,noSuchInstance}, - {noValue,noSuchInstance}, {noValue,noSuchInstance}, - {noValue,noSuchInstance}, {noValue,noSuchInstance}, - {noValue,noSuchInstance}, {noValue,noSuchInstance}, - {noValue,noSuchInstance}, {noValue,noSuchInstance}] = - os_mon_mib:load_table(get, [3, 102, 111, 111], - [?loadErlNodeName, - ?loadSystemTotalMemory, - ?loadSystemUsedMemory, - ?loadLargestErlProcess, - ?loadLargestErlProcessUsedMemory, - ?loadCpuLoad, - ?loadCpuLoad5, - ?loadCpuLoad15, - ?loadOsWordsize, - ?loadSystemTotalMemory64, - ?loadSystemUsedMemory64, - ?loadLargestErlProcessUsedMemory64]), + [{noValue,noSuchInstance}, {noValue,noSuchInstance}, + {noValue,noSuchInstance}, {noValue,noSuchInstance}, + {noValue,noSuchInstance}, {noValue,noSuchInstance}, + {noValue,noSuchInstance}, {noValue,noSuchInstance}, + {noValue,noSuchInstance}, {noValue,noSuchInstance}, + {noValue,noSuchInstance}, {noValue,noSuchInstance}] = + os_mon_mib:load_table(get, [3, 102, 111, 111], + [?loadErlNodeName, + ?loadSystemTotalMemory, + ?loadSystemUsedMemory, + ?loadLargestErlProcess, + ?loadLargestErlProcessUsedMemory, + ?loadCpuLoad, + ?loadCpuLoad5, + ?loadCpuLoad15, + ?loadOsWordsize, + ?loadSystemTotalMemory64, + ?loadSystemUsedMemory64, + ?loadLargestErlProcessUsedMemory64]), ok. %%--------------------------------------------------------------------- -sys_tot_mem(doc) -> - []; -sys_tot_mem(suite) -> - []; sys_tot_mem(Config) when is_list(Config) -> - ?line [{[?loadSystemTotalMemory, Len | NodeStr], Mem}] = - os_mon_mib:load_table(get_next, [], [?loadSystemTotalMemory]), - ?line Len = length(NodeStr), - ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), + [{[?loadSystemTotalMemory, Len | NodeStr], Mem}] = + os_mon_mib:load_table(get_next, [], [?loadSystemTotalMemory]), + Len = length(NodeStr), + true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), case Mem of - Mem when is_integer(Mem) -> - ok; - _ -> - ?line test_server:fail(sys_tot_mem_value_not_integer) + Mem when is_integer(Mem) -> + ok; + _ -> + ct:fail(sys_tot_mem_value_not_integer) end. -sys_used_mem(doc) -> - []; -sys_used_mem(suite) -> []; sys_used_mem(Config) when is_list(Config) -> - ?line [{[?loadSystemUsedMemory, Len | NodeStr], Mem}] = - os_mon_mib:load_table(get_next,[], [?loadSystemUsedMemory]), - ?line Len = length(NodeStr), - ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), + [{[?loadSystemUsedMemory, Len | NodeStr], Mem}] = + os_mon_mib:load_table(get_next,[], [?loadSystemUsedMemory]), + Len = length(NodeStr), + true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), case Mem of - Mem when is_integer(Mem) -> - ok; - _ -> - ?line test_server:fail(sys_used_mem_value_not_integer) + Mem when is_integer(Mem) -> + ok; + _ -> + ct:fail(sys_used_mem_value_not_integer) end. -large_erl_process(doc) -> - []; -large_erl_process(suite) -> - []; large_erl_process(Config) when is_list(Config) -> {_, _, {Pid, _}} = memsup:get_memory_data(), PidStr = lists:flatten(io_lib:format("~w", [Pid])), - ?line [{[?loadLargestErlProcess, Len | NodeStr], PidStr}] = - os_mon_mib:load_table(get_next,[], [?loadLargestErlProcess]), - ?line Len = length(NodeStr), - ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), + [{[?loadLargestErlProcess, Len | NodeStr], PidStr}] = + os_mon_mib:load_table(get_next,[], [?loadLargestErlProcess]), + Len = length(NodeStr), + true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), ok. -large_erl_process_mem(doc) -> - []; -large_erl_process_mem(suite) -> - []; large_erl_process_mem(Config) when is_list(Config) -> - ?line [{[?loadLargestErlProcessUsedMemory, Len | NodeStr], Mem}] = - os_mon_mib:load_table(get_next,[], - [?loadLargestErlProcessUsedMemory]), - ?line Len = length(NodeStr), - ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), - - case Mem of - Mem when is_integer(Mem) -> - ok; - _ -> - ?line test_server:fail(erl_pid_mem_value_not_integer) + [{[?loadLargestErlProcessUsedMemory, Len | NodeStr], Mem}] = + os_mon_mib:load_table(get_next,[], + [?loadLargestErlProcessUsedMemory]), + Len = length(NodeStr), + true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), + + case Mem of + Mem when is_integer(Mem) -> + ok; + _ -> + ct:fail(erl_pid_mem_value_not_integer) end. -cpu_load(doc) -> - []; -cpu_load(suite) -> - []; cpu_load(Config) when is_list(Config) -> - ?line [{[?loadCpuLoad, Len | NodeStr], Load}] = - os_mon_mib:load_table(get_next,[], [?loadCpuLoad]), - ?line Len = length(NodeStr), - ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), + [{[?loadCpuLoad, Len | NodeStr], Load}] = + os_mon_mib:load_table(get_next,[], [?loadCpuLoad]), + Len = length(NodeStr), + true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), case Load of - Load when is_integer(Load) -> - ok; - _ -> - ?line test_server:fail(cpu_load_value_not_integer) + Load when is_integer(Load) -> + ok; + _ -> + ct:fail(cpu_load_value_not_integer) end. -cpu_load5(doc) -> - []; -cpu_load5(suite) -> - []; cpu_load5(Config) when is_list(Config) -> - ?line [{[?loadCpuLoad5, Len | NodeStr], Load}] = - os_mon_mib:load_table(get_next,[], [?loadCpuLoad5]), - ?line Len = length(NodeStr), - ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), + [{[?loadCpuLoad5, Len | NodeStr], Load}] = + os_mon_mib:load_table(get_next,[], [?loadCpuLoad5]), + Len = length(NodeStr), + true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), case Load of - Load when is_integer(Load) -> - ok; - _ -> - ?line test_server:fail(cpu_load5_value_not_integer) + Load when is_integer(Load) -> + ok; + _ -> + ct:fail(cpu_load5_value_not_integer) end. -cpu_load15(doc) -> - []; -cpu_load15(suite) -> - []; cpu_load15(Config) when is_list(Config) -> - ?line [{[?loadCpuLoad15, Len | NodeStr], Load}] = - os_mon_mib:load_table(get_next,[], [?loadCpuLoad15]), - ?line Len = length(NodeStr), - ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), - - case Load of - Load when is_integer(Load) -> - ok; - _ -> - ?line test_server:fail(cpu_load15_value_not_integer) - end. - -os_wordsize(doc) -> - []; -os_wordsize(suite) -> - []; + [{[?loadCpuLoad15, Len | NodeStr], Load}] = + os_mon_mib:load_table(get_next,[], [?loadCpuLoad15]), + Len = length(NodeStr), + true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), + + case Load of + Load when is_integer(Load) -> + ok; + _ -> + ct:fail(cpu_load15_value_not_integer) + end. + os_wordsize(Config) when is_list(Config) -> - ?line [{[?loadOsWordsize, Len | NodeStr], Wordsize}] = - os_mon_mib:load_table(get_next,[], [?loadOsWordsize]), - ?line Len = length(NodeStr), - ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), - - case Wordsize of - Wordsize when is_integer(Wordsize) -> - ok; - _ -> - ?line test_server:fail(os_wordsize_value_not_integer) - end. - -sys_tot_mem64(doc) -> - []; -sys_tot_mem64(suite) -> - []; + [{[?loadOsWordsize, Len | NodeStr], Wordsize}] = + os_mon_mib:load_table(get_next,[], [?loadOsWordsize]), + Len = length(NodeStr), + true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), + + case Wordsize of + Wordsize when is_integer(Wordsize) -> + ok; + _ -> + ct:fail(os_wordsize_value_not_integer) + end. + sys_tot_mem64(Config) when is_list(Config) -> - ?line [{[?loadSystemTotalMemory64, Len | NodeStr], Mem}] = - os_mon_mib:load_table(get_next, [], [?loadSystemTotalMemory64]), - ?line Len = length(NodeStr), - ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), + [{[?loadSystemTotalMemory64, Len | NodeStr], Mem}] = + os_mon_mib:load_table(get_next, [], [?loadSystemTotalMemory64]), + Len = length(NodeStr), + true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), case Mem of - Mem when is_integer(Mem) -> - ok; - _ -> - ?line test_server:fail(sys_tot_mem_value_not_integer) + Mem when is_integer(Mem) -> + ok; + _ -> + ct:fail(sys_tot_mem_value_not_integer) end. -sys_used_mem64(doc) -> - []; -sys_used_mem64(suite) -> []; sys_used_mem64(Config) when is_list(Config) -> - ?line [{[?loadSystemUsedMemory64, Len | NodeStr], Mem}] = - os_mon_mib:load_table(get_next,[], [?loadSystemUsedMemory64]), - ?line Len = length(NodeStr), - ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), + [{[?loadSystemUsedMemory64, Len | NodeStr], Mem}] = + os_mon_mib:load_table(get_next,[], [?loadSystemUsedMemory64]), + Len = length(NodeStr), + true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), case Mem of - Mem when is_integer(Mem) -> - ok; - _ -> - ?line test_server:fail(sys_used_mem_value_not_integer) + Mem when is_integer(Mem) -> + ok; + _ -> + ct:fail(sys_used_mem_value_not_integer) end. -large_erl_process_mem64(doc) -> - []; -large_erl_process_mem64(suite) -> - []; large_erl_process_mem64(Config) when is_list(Config) -> - ?line [{[?loadLargestErlProcessUsedMemory64, Len | NodeStr], Mem}] = - os_mon_mib:load_table(get_next,[], - [?loadLargestErlProcessUsedMemory64]), - ?line Len = length(NodeStr), - ?line true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), - - case Mem of - Mem when is_integer(Mem) -> - ok; - _ -> - ?line test_server:fail(erl_pid_mem_value_not_integer) + [{[?loadLargestErlProcessUsedMemory64, Len | NodeStr], Mem}] = + os_mon_mib:load_table(get_next,[], + [?loadLargestErlProcessUsedMemory64]), + Len = length(NodeStr), + true = lists:member(list_to_atom(NodeStr), [node() | nodes()]), + + case Mem of + Mem when is_integer(Mem) -> + ok; + _ -> + ct:fail(erl_pid_mem_value_not_integer) end. %%--------------------------------------------------------------------- -get_disk_table(doc) -> - ["Simulates get calls to test the instrumentation function " - "for the diskTable."]; -get_disk_table(suite) -> - []; +%% Simulates get calls to test the instrumentation function +%% for the diskTable. get_disk_table(Config) when is_list(Config) -> DiskData = disksup:get_disk_data(), DiskDataLen = length(DiskData), if - DiskDataLen > 0 -> - ?line [{value, Value}] = - os_mon_mib:disk_table(get, [1,1], [?diskDescr]), - - case is_list(Value) of - true -> - ok; - false -> - ?line test_server:fail(value_not_a_string) - end, - - ?line Values = os_mon_mib:disk_table(get, [1,1], - [?diskId, - ?diskKBytes, - ?diskCapacity]), - - IsInt = fun({value, Val}) when is_integer(Val) -> - true; - (_) -> - false - end, - - NewValues = lists:filter(IsInt, Values), - - case length(NewValues) of - 3 -> - ok; - _ -> - ?line test_server:fail(value_not_integer) - end + DiskDataLen > 0 -> + [{value, Value}] = + os_mon_mib:disk_table(get, [1,1], [?diskDescr]), + + case is_list(Value) of + true -> + ok; + false -> + ct:fail(value_not_a_string) + end, + + Values = os_mon_mib:disk_table(get, [1,1], + [?diskId, + ?diskKBytes, + ?diskCapacity]), + + IsInt = fun({value, Val}) when is_integer(Val) -> + true; + (_) -> + false + end, + + NewValues = lists:filter(IsInt, Values), + + case length(NewValues) of + 3 -> + ok; + _ -> + ct:fail(value_not_integer) + end end, - ?line [{noValue,noSuchInstance}, {noValue,noSuchInstance}, - {noValue,noSuchInstance}, {noValue,noSuchInstance}] = - os_mon_mib:disk_table(get, [1, DiskDataLen + 1], [?diskId, - ?diskDescr, - ?diskKBytes, - ?diskCapacity]), + [{noValue,noSuchInstance}, {noValue,noSuchInstance}, + {noValue,noSuchInstance}, {noValue,noSuchInstance}] = + os_mon_mib:disk_table(get, [1, DiskDataLen + 1], [?diskId, + ?diskDescr, + ?diskKBytes, + ?diskCapacity]), ok. %%--------------------------------------------------------------------- -disk_descr(doc) -> - []; -disk_descr(suite) -> - []; disk_descr(Config) when is_list(Config) -> - ?line [{[?diskDescr, 1,1], Descr}] = - os_mon_mib:disk_table(get_next, [], [?diskDescr]), + [{[?diskDescr, 1,1], Descr}] = + os_mon_mib:disk_table(get_next, [], [?diskDescr]), case Descr of - Descr when is_list(Descr) -> - ok; - _ -> - ?line test_server:fail(disk_descr_value_not_a_string) + Descr when is_list(Descr) -> + ok; + _ -> + ct:fail(disk_descr_value_not_a_string) end. -disk_kbytes(doc) -> - []; -disk_kbytes(suite) -> []; disk_kbytes(Config) when is_list(Config) -> - ?line [{[?diskKBytes, 1,1], Kbytes}] = - os_mon_mib:disk_table(get_next,[], [?diskKBytes]), + [{[?diskKBytes, 1,1], Kbytes}] = + os_mon_mib:disk_table(get_next,[], [?diskKBytes]), case Kbytes of - Kbytes when is_integer(Kbytes) -> - ok; - _ -> - ?line test_server:fail(disk_kbytes_value_not_integer) + Kbytes when is_integer(Kbytes) -> + ok; + _ -> + ct:fail(disk_kbytes_value_not_integer) end. -disk_capacity(doc) -> - []; -disk_capacity(suite) -> []; disk_capacity(Config) when is_list(Config) -> - ?line [{[?diskCapacity, 1,1], Capacity}] = - os_mon_mib:disk_table(get_next,[], [?diskCapacity]), + [{[?diskCapacity, 1,1], Capacity}] = + os_mon_mib:disk_table(get_next,[], [?diskCapacity]), case Capacity of - Capacity when is_integer(Capacity) -> - ok; - _ -> - ?line test_server:fail(disk_capacity_value_not_integer) + Capacity when is_integer(Capacity) -> + ok; + _ -> + ct:fail(disk_capacity_value_not_integer) end. %%--------------------------------------------------------------------- -real_snmp_request(doc) -> - ["Starts an snmp manager and sends a real snmp-request. i.e. " - "sends a udp message on the correct format."]; -real_snmp_request(suite) -> []; +%% Starts an snmp manager and sends a real snmp-request. i.e. +%% sends a udp message on the correct format. real_snmp_request(Config) when is_list(Config) -> NodStr = atom_to_list(node()), Len = length(NodStr), {_, _, {Pid, _}} = memsup:get_memory_data(), PidStr = lists:flatten(io_lib:format("~w", [Pid])), io:format("FOO: ~p~n", [PidStr]), - ?line ok = snmp_get([?loadEntry ++ - [?loadLargestErlProcess, Len | NodStr]], - PidStr), - ?line ok = snmp_get_next([?loadEntry ++ - [?loadSystemUsedMemory, Len | NodStr]], - ?loadEntry ++ [?loadSystemUsedMemory + 1, Len - | NodStr], PidStr), - ?line ok = snmp_set([?loadEntry ++ [?loadLargestErlProcess, Len | NodStr]], - s, "<0.101.0>", Config), + ok = snmp_get([?loadEntry ++ + [?loadLargestErlProcess, Len | NodStr]], + PidStr), + ok = snmp_get_next([?loadEntry ++ + [?loadSystemUsedMemory, Len | NodStr]], + ?loadEntry ++ [?loadSystemUsedMemory + 1, Len + | NodStr], PidStr), + ok = snmp_set([?loadEntry ++ [?loadLargestErlProcess, Len | NodStr]], + s, "<0.101.0>", Config), ok. -otp_7441(doc) -> - ["Starts an snmp manager and requests total memory. Was previously - integer32 which was errornous on 64 bit machines."]; -otp_7441(suite) -> - []; +%% Starts an snmp manager and requests total memory. Was previously +%% integer32 which was errornous on 64 bit machines. otp_7441(Config) when is_list(Config) -> NodStr = atom_to_list(node()), Len = length(NodStr), Oids = [Oid|_] = [?loadEntry ++ [?loadSystemTotalMemory, Len | NodStr]], {noError,0,[#varbind{oid = Oid, variabletype = 'Unsigned32'}]} = - ct_snmp:get_values(os_mon_mib_test, Oids, snmp_mgr_agent), + ct_snmp:get_values(os_mon_mib_test, Oids, snmp_mgr_agent), ok. @@ -636,9 +541,8 @@ otp_7441(Config) when is_list(Config) -> %% Internal functions %%--------------------------------------------------------------------- start_node() -> - ?line Pa = filename:dirname(code:which(?MODULE)), - ?line {ok,Node} = test_server:start_node(testnisse, slave, - [{args, " -pa " ++ Pa}]), + Pa = filename:dirname(code:which(?MODULE)), + {ok,Node} = test_server:start_node(testnisse, slave, [{args, " -pa " ++ Pa}]), Node. stop_node(Node) -> @@ -648,27 +552,27 @@ del_dir(Dir) -> io:format("Deleting: ~s~n",[Dir]), {ok, Files} = file:list_dir(Dir), FullPathFiles = lists:map(fun(File) -> filename:join(Dir, File) end, - Files), + Files), lists:foreach(fun file:delete/1, FullPathFiles), file:del_dir(Dir). %%--------------------------------------------------------------------- snmp_get(Oids = [Oid |_], Result) -> {noError,0,[#varbind{oid = Oid, - variabletype = 'OCTET STRING', - value = Result}]} = - ct_snmp:get_values(os_mon_mib_test, Oids, snmp_mgr_agent), + variabletype = 'OCTET STRING', + value = Result}]} = + ct_snmp:get_values(os_mon_mib_test, Oids, snmp_mgr_agent), ok. snmp_get_next(Oids, NextOid, Result) -> {noError,0,[#varbind{oid = NextOid, - variabletype = 'OCTET STRING', - value = Result}]} = - ct_snmp:get_next_values(os_mon_mib_test, Oids, snmp_mgr_agent), + variabletype = 'OCTET STRING', + value = Result}]} = + ct_snmp:get_next_values(os_mon_mib_test, Oids, snmp_mgr_agent), ok. snmp_set(Oid, ValuType, Value, Config) -> {notWritable, _, _} = - ct_snmp:set_values(os_mon_mib_test, [{Oid, ValuType, Value}], - snmp_mgr_agent, Config), + ct_snmp:set_values(os_mon_mib_test, [{Oid, ValuType, Value}], + snmp_mgr_agent, Config), ok. diff --git a/lib/os_mon/test/os_sup_SUITE.erl b/lib/os_mon/test/os_sup_SUITE.erl index 5857faa0a6..82c04ceaae 100644 --- a/lib/os_mon/test/os_sup_SUITE.erl +++ b/lib/os_mon/test/os_sup_SUITE.erl @@ -21,17 +21,13 @@ -include_lib("common_test/include/ct.hrl"). %% Test server specific exports --export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]). +-export([all/0, suite/0]). -export([init_per_suite/1, end_per_suite/1]). --export([init_per_testcase/2, end_per_testcase/2]). %% Test cases -export([message/1]). -export([config/1, port/1]). -%% Default timetrap timeout (set in init_per_testcase) --define(default_timeout, ?t:minutes(1)). - -define(TAG, test_tag). -define(MFA, {?MODULE, test_mfa, [?TAG]}). @@ -39,86 +35,64 @@ init_per_suite(Config) when is_list(Config) -> spawn(fun() -> message_receptor() end), - ?line application:load(os_mon), - ?line ok = application:set_env(os_mon, start_os_sup, true), - ?line ok = application:set_env(os_mon, os_sup_mfa, ?MFA), - ?line ok = application:set_env(os_mon, os_sup_enable, false), - ?line ok = application:start(os_mon), + application:load(os_mon), + ok = application:set_env(os_mon, start_os_sup, true), + ok = application:set_env(os_mon, os_sup_mfa, ?MFA), + ok = application:set_env(os_mon, os_sup_enable, false), + ok = application:start(os_mon), Config. end_per_suite(Config) when is_list(Config) -> - ?line application:stop(os_mon), - ?line ok = application:set_env(os_mon, start_os_sup, false), + application:stop(os_mon), + ok = application:set_env(os_mon, start_os_sup, false), MFA = {os_sup, error_report, [std_error]}, - ?line ok = application:set_env(os_mon, os_sup_mfa, MFA), - ?line ok = application:set_env(os_mon, os_sup_enable, true), - ?line exit(whereis(message_receptor), done), + ok = application:set_env(os_mon, os_sup_mfa, MFA), + ok = application:set_env(os_mon, os_sup_enable, true), + exit(whereis(message_receptor), done), Config. -init_per_testcase(_Case, Config) -> - Dog = ?t:timetrap(?default_timeout), - [{watchdog,Dog} | Config]. - -end_per_testcase(_Case, Config) -> - Dog = ?config(watchdog, Config), - ?t:timetrap_cancel(Dog), - ok. - -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> case test_server:os_type() of - {unix, sunos} -> [message, config, port]; - {win32, _OSname} -> [message]; - OS -> - Str = io_lib:format("os_sup not available for ~p", - [OS]), - {skip, lists:flatten(Str)} + {unix, sunos} -> [message, config, port]; + {win32, _OSname} -> [message]; + OS -> + Str = io_lib:format("os_sup not available for ~p", + [OS]), + {skip, lists:flatten(Str)} end. -groups() -> - []. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - -message(suite) -> - []; -message(doc) -> - ["Test OS message handling"]; +%% Test OS message handling message(Config) when is_list(Config) -> %% Fake an OS message Data = "10H11386278426HSystem4HTest5HError5HTesto", - ?line os_sup_server ! {faked_port, {data, Data}}, + os_sup_server ! {faked_port, {data, Data}}, %% Check with message_receptor that it has been received - ?t:sleep(?t:seconds(1)), + ct:sleep({seconds,1}), Msg = - case ?t:os_type() of - {unix, sunos} -> - {?TAG, Data}; - {win32, _} -> - {?TAG,{{1138,627842,0},"System","Test","Error","Testo"}} - end, - ?line message_receptor ! {check, self(), Msg}, + case ?t:os_type() of + {unix, sunos} -> + {?TAG, Data}; + {win32, _} -> + {?TAG,{{1138,627842,0},"System","Test","Error","Testo"}} + end, + message_receptor ! {check, self(), Msg}, receive - {result, true} -> - ok; - {result, Rec} -> - ?t:fail({no_message, Rec}) + {result, true} -> + ok; + {result, Rec} -> + ct:fail({no_message, Rec}) end, ok. -config(suite) -> - []; -config(doc) -> - ["Test configuration"]; +%% Test configuration config(Config) when is_list(Config) -> %% os_sup_enable==true and os_sup_own/os_sup_syslogconf cannot @@ -130,45 +104,42 @@ config(Config) when is_list(Config) -> ok. -port(suite) -> - []; -port(doc) -> - ["Test that os_sup handles a terminating port program"]; +%% Test that os_sup handles a terminating port program port(Config) when is_list(Config) -> - ?line Str = os:cmd("ps -e | grep '[f]errule'"), + Str = os:cmd("ps -e | grep '[f]errule'"), case io_lib:fread("~s", Str) of - {ok, [Pid], _Rest} -> - - %% Monitor os_sup_server - ?line MonRef = erlang:monitor(process, os_sup_server), - - %% Kill the port program - case os:cmd("kill -9 " ++ Pid) of - [] -> - - %% os_sup_server should now terminate - receive - {'DOWN', MonRef, _, _, {port_died, _Reason}} -> - ok; - {'DOWN', MonRef, _, _, Reason} -> - ?line ?t:fail({unexpected_exit_reason, Reason}) - after - 3000 -> - ?line ?t:fail(still_alive) - end, - - %% Give os_mon_sup time to restart os_sup - ?t:sleep(?t:seconds(3)), - ?line true = is_pid(whereis(os_sup_server)), - - ok; - - Line -> - erlang:demonitor(MonRef), - {skip, {not_killed, Line}} - end; - _ -> - {skip, {os_pid_not_found}} + {ok, [Pid], _Rest} -> + + %% Monitor os_sup_server + MonRef = erlang:monitor(process, os_sup_server), + + %% Kill the port program + case os:cmd("kill -9 " ++ Pid) of + [] -> + + %% os_sup_server should now terminate + receive + {'DOWN', MonRef, _, _, {port_died, _Reason}} -> + ok; + {'DOWN', MonRef, _, _, Reason} -> + ct:fail({unexpected_exit_reason, Reason}) + after + 3000 -> + ct:fail(still_alive) + end, + + %% Give os_mon_sup time to restart os_sup + ct:sleep({seconds,3}), + true = is_pid(whereis(os_sup_server)), + + ok; + + Line -> + erlang:demonitor(MonRef), + {skip, {not_killed, Line}} + end; + _ -> + {skip, {os_pid_not_found}} end. %%---------------------------------------------------------------------- @@ -184,18 +155,18 @@ message_receptor() -> message_receptor(Received) -> receive - %% Check if a certain message has been received - {check, From, Msg} -> - case lists:member(Msg, Received) of - true -> - From ! {result, true}, - message_receptor(lists:delete(Msg, Received)); - false -> - From ! {result, Received}, - message_receptor(Received) - end; - - %% Save all other messages - Msg -> - message_receptor([Msg|Received]) + %% Check if a certain message has been received + {check, From, Msg} -> + case lists:member(Msg, Received) of + true -> + From ! {result, true}, + message_receptor(lists:delete(Msg, Received)); + false -> + From ! {result, Received}, + message_receptor(Received) + end; + + %% Save all other messages + Msg -> + message_receptor([Msg|Received]) end. diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml index 82bede69d0..53d534ef19 100644 --- a/lib/ssl/doc/src/ssl.xml +++ b/lib/ssl/doc/src/ssl.xml @@ -421,7 +421,6 @@ fun(srp, Username :: string(), UserState :: term()) -> <warning><p>Using <c>{padding_check, boolean()}</c> makes TLS vulnerable to the Poodle attack.</p></warning> - </section> <section> @@ -522,9 +521,43 @@ fun(srp, Username :: string(), UserState :: term()) -> be supported by the server for the prevention to work. </p></warning> </item> - </taglist> + <tag><marker id="client_signature_algs"/><c>{signature_algs, [{hash(), ecdsa | rsa | dsa}]}</c></tag> + <item> + <p>In addition to the algorithms negotiated by the cipher + suite used for key exchange, payload encryption, message + authentication and pseudo random calculation, the TLS signature + algorithm extension <url + href="http://www.ietf.org/rfc/rfc5246.txt">Section 7.4.1.4.1 in RFC 5246</url> may be + used, from TLS 1.2, to negotiate which signature algorithm to use during the + TLS handshake. If no lower TLS versions than 1.2 are supported, + the client will send a TLS signature algorithm extension + with the algorithms specified by this option. + Defaults to + + <code>[ +%% SHA2 +{sha512, ecdsa}, +{sha512, rsa}, +{sha384, ecdsa}, +{sha384, rsa}, +{sha256, ecdsa}, +{sha256, rsa}, +{sha224, ecdsa}, +{sha224, rsa}, +%% SHA +{sha, ecdsa}, +{sha, rsa}, +{sha, dsa}, +]</code> + + The algorithms should be in the preferred order. + Selected signature algorithm can restrict which hash functions + that may be selected. Default support for {md5, rsa} removed in ssl-8.0 + </p> + </item> + </taglist> </section> - + <section> <title>SSL OPTION DESCRIPTIONS - SERVER SIDE</title> @@ -651,6 +684,14 @@ fun(srp, Username :: string(), UserState :: term()) -> <item>If true, use the server's preference for cipher selection. If false (the default), use the client's preference. </item> + + <tag><c>{signature_algs, [{hash(), ecdsa | rsa | dsa}]}</c></tag> + <item><p> The algorithms specified by + this option will be the ones accepted by the server in a signature algorithm + negotiation, introduced in TLS-1.2. The algorithms will also be offered to the client if a + client certificate is requested. For more details see the <seealso marker="#client_signature_algs">corresponding client option</seealso>. + </p> </item> + </taglist> </section> diff --git a/lib/ssl/src/dtls_connection.erl b/lib/ssl/src/dtls_connection.erl index 153d3fef48..e490de7eeb 100644 --- a/lib/ssl/src/dtls_connection.erl +++ b/lib/ssl/src/dtls_connection.erl @@ -196,8 +196,7 @@ hello(start, #state{host = Host, port = Port, role = client, {Record, State} = next_record(State1), next_state(hello, hello, Record, State); -hello(Hello = #client_hello{client_version = ClientVersion, - extensions = #hello_extensions{hash_signs = HashSigns}}, +hello(Hello = #client_hello{client_version = ClientVersion}, State = #state{connection_states = ConnectionStates0, port = Port, session = #session{own_certificate = Cert} = Session0, renegotiation = {Renegotiation, _}, @@ -209,9 +208,7 @@ hello(Hello = #client_hello{client_version = ClientVersion, {Version, {Type, Session}, ConnectionStates, #hello_extensions{ec_point_formats = EcPointFormats, - elliptic_curves = EllipticCurves} = ServerHelloExt} -> - HashSign = ssl_handshake:select_hashsign(HashSigns, Cert, - dtls_v1:corresponding_tls_version(Version)), + elliptic_curves = EllipticCurves} = ServerHelloExt, HashSign} -> ssl_connection:hello({common_client_hello, Type, ServerHelloExt, HashSign}, State#state{connection_states = ConnectionStates, negotiated_version = Version, diff --git a/lib/ssl/src/dtls_handshake.erl b/lib/ssl/src/dtls_handshake.erl index 22c0ce7a13..50c84b712f 100644 --- a/lib/ssl/src/dtls_handshake.erl +++ b/lib/ssl/src/dtls_handshake.erl @@ -94,7 +94,10 @@ hello(#server_hello{server_version = Version, random = Random, hello(#client_hello{client_version = ClientVersion}, _Options, {_,_,_,_,ConnectionStates,_}, _Renegotiation) -> %% Return correct typ to make dialyzer happy until we have time to make the real imp. - {ClientVersion, {new, #session{}}, ConnectionStates, #hello_extensions{}}. + HashSigns = tls_v1:default_signature_algs(dtls_v1:corresponding_tls_version(ClientVersion)), + {ClientVersion, {new, #session{}}, ConnectionStates, #hello_extensions{}, + %% Placeholder for real hasign handling + hd(HashSigns)}. %% hello(Address, Port, %% #ssl_tls{epoch = _Epoch, sequence_number = _Seq, diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index 780bef5877..9045f8fef9 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -700,6 +700,10 @@ handle_options(Opts0, Role) -> srp_identity = handle_option(srp_identity, Opts, undefined), ciphers = handle_cipher_option(proplists:get_value(ciphers, Opts, []), RecordCb:highest_protocol_version(Versions)), + signature_algs = handle_hashsigns_option(proplists:get_value(signature_algs, Opts, + default_option_role(server, + tls_v1:default_signature_algs(Versions), Role)), + RecordCb:highest_protocol_version(Versions)), %% Server side option reuse_session = handle_option(reuse_session, Opts, ReuseSessionFun), reuse_sessions = handle_option(reuse_sessions, Opts, true), @@ -749,7 +753,7 @@ handle_options(Opts0, Role) -> alpn_preferred_protocols, next_protocols_advertised, client_preferred_next_protocols, log_alert, server_name_indication, honor_cipher_order, padding_check, crl_check, crl_cache, - fallback], + fallback, signature_algs], SockOpts = lists:foldl(fun(Key, PropList) -> proplists:delete(Key, PropList) @@ -989,6 +993,18 @@ validate_option(crl_cache, {Cb, {_Handle, Options}} = Value) when is_atom(Cb) an validate_option(Opt, Value) -> throw({error, {options, {Opt, Value}}}). +handle_hashsigns_option(Value, {Major, Minor} = Version) when is_list(Value) + andalso Major >= 3 andalso Minor >= 3-> + case tls_v1:signature_algs(Version, Value) of + [] -> + throw({error, {options, no_supported_algorithms, {signature_algs, Value}}}); + _ -> + Value + end; +handle_hashsigns_option(_, {Major, Minor} = Version) when Major >= 3 andalso Minor >= 3-> + handle_hashsigns_option(tls_v1:default_signature_algs(Version), Version); +handle_hashsigns_option(_, _Version) -> + undefined. validate_options([]) -> []; @@ -1285,6 +1301,13 @@ new_ssl_options([{server_name_indication, Value} | Rest], #ssl_options{} = Opts, new_ssl_options(Rest, Opts#ssl_options{server_name_indication = validate_option(server_name_indication, Value)}, RecordCB); new_ssl_options([{honor_cipher_order, Value} | Rest], #ssl_options{} = Opts, RecordCB) -> new_ssl_options(Rest, Opts#ssl_options{honor_cipher_order = validate_option(honor_cipher_order, Value)}, RecordCB); +new_ssl_options([{signature_algs, Value} | Rest], #ssl_options{} = Opts, RecordCB) -> + new_ssl_options(Rest, + Opts#ssl_options{signature_algs = + handle_hashsigns_option(Value, + RecordCB:highest_protocol_version())}, + RecordCB); + new_ssl_options([{Key, Value} | _Rest], #ssl_options{}, _) -> throw({error, {options, {Key, Value}}}). diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl index d737f74aa3..cbe3a2a056 100644 --- a/lib/ssl/src/ssl_cipher.erl +++ b/lib/ssl/src/ssl_cipher.erl @@ -43,11 +43,12 @@ -export_type([cipher_suite/0, erl_cipher_suite/0, openssl_cipher_suite/0, - key_algo/0]). + hash/0, key_algo/0, sign_algo/0]). -type cipher() :: null |rc4_128 | idea_cbc | des40_cbc | des_cbc | '3des_ede_cbc' | aes_128_cbc | aes_256_cbc | aes_128_gcm | aes_256_gcm | chacha20_poly1305. -type hash() :: null | sha | md5 | sha224 | sha256 | sha384 | sha512. +-type sign_algo() :: rsa | dsa | ecdsa. -type key_algo() :: null | rsa | dhe_rsa | dhe_dss | ecdhe_ecdsa| ecdh_ecdsa | ecdh_rsa| srp_rsa| srp_dss | psk | dhe_psk | rsa_psk | dh_anon | ecdh_anon | srp_anon. -type erl_cipher_suite() :: {key_algo(), cipher(), hash()} % Pre TLS 1.2 %% TLS 1.2, internally PRE TLS 1.2 will use default_prf diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index ec7d086934..f774873269 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -304,13 +304,9 @@ hello(#hello_request{}, #state{role = client} = State0, Connection) -> {Record, State} = Connection:next_record(State0), Connection:next_state(hello, hello, Record, State); -hello({common_client_hello, Type, ServerHelloExt, NegotiatedHashSign}, +hello({common_client_hello, Type, ServerHelloExt}, State, Connection) -> - do_server_hello(Type, ServerHelloExt, - %% Note NegotiatedHashSign is only negotiated for real if - %% if TLS version is at least TLS-1.2 - State#state{hashsign_algorithm = NegotiatedHashSign}, Connection); - + do_server_hello(Type, ServerHelloExt, State, Connection); hello(timeout, State, _) -> {next_state, hello, State, hibernate}; @@ -442,7 +438,8 @@ certify(#server_key_exchange{exchange_keys = Keys}, Alg == srp_dss; Alg == srp_rsa; Alg == srp_anon -> Params = ssl_handshake:decode_server_key(Keys, Alg, Version), - HashSign = negotiated_hashsign(Params#server_key_params.hashsign, Alg, Version), + %% Use negotiated value if TLS-1.2 otherwhise return default + HashSign = negotiated_hashsign(Params#server_key_params.hashsign, Alg, PubKeyInfo, Version), case is_anonymous(Alg) of true -> calculate_secret(Params#server_key_params.params, @@ -464,11 +461,18 @@ certify(#server_key_exchange{} = Msg, certify(#certificate_request{hashsign_algorithms = HashSigns}, #state{session = #session{own_certificate = Cert}, - negotiated_version = Version} = State0, Connection) -> - HashSign = ssl_handshake:select_hashsign(HashSigns, Cert, Version), - {Record, State} = Connection:next_record(State0#state{client_certificate_requested = true}), - Connection:next_state(certify, certify, Record, - State#state{cert_hashsign_algorithm = HashSign}); + key_algorithm = KeyExAlg, + ssl_options = #ssl_options{signature_algs = SupportedHashSigns}, + negotiated_version = Version} = State0, Connection) -> + + case ssl_handshake:select_hashsign(HashSigns, Cert, KeyExAlg, SupportedHashSigns, Version) of + #alert {} = Alert -> + Connection:handle_own_alert(Alert, Version, certify, State0); + NegotiatedHashSign -> + {Record, State} = Connection:next_record(State0#state{client_certificate_requested = true}), + Connection:next_state(certify, certify, Record, + State#state{cert_hashsign_algorithm = NegotiatedHashSign}) + end; %% PSK and RSA_PSK might bypass the Server-Key-Exchange certify(#server_hello_done{}, @@ -576,13 +580,15 @@ cipher(#hello_request{}, State0, Connection) -> cipher(#certificate_verify{signature = Signature, hashsign_algorithm = CertHashSign}, #state{role = server, - public_key_info = {Algo, _, _} =PublicKeyInfo, + key_algorithm = KexAlg, + public_key_info = PublicKeyInfo, negotiated_version = Version, session = #session{master_secret = MasterSecret}, tls_handshake_history = Handshake } = State0, Connection) -> - - HashSign = ssl_handshake:select_hashsign_algs(CertHashSign, Algo, Version), + + %% Use negotiated value if TLS-1.2 otherwhise return default + HashSign = negotiated_hashsign(CertHashSign, KexAlg, PublicKeyInfo, Version), case ssl_handshake:certificate_verify(Signature, PublicKeyInfo, Version, HashSign, MasterSecret, Handshake) of valid -> @@ -1448,7 +1454,8 @@ rsa_psk_key_exchange(Version, PskIdentity, PremasterSecret, PublicKeyInfo = {Alg rsa_psk_key_exchange(_, _, _, _) -> throw (?ALERT_REC(?FATAL,?HANDSHAKE_FAILURE)). -request_client_cert(#state{ssl_options = #ssl_options{verify = verify_peer}, +request_client_cert(#state{ssl_options = #ssl_options{verify = verify_peer, + signature_algs = SupportedHashSigns}, connection_states = ConnectionStates0, cert_db = CertDbHandle, cert_db_ref = CertDbRef, @@ -1456,7 +1463,9 @@ request_client_cert(#state{ssl_options = #ssl_options{verify = verify_peer}, #connection_state{security_parameters = #security_parameters{cipher_suite = CipherSuite}} = ssl_record:pending_connection_state(ConnectionStates0, read), - Msg = ssl_handshake:certificate_request(CipherSuite, CertDbHandle, CertDbRef, Version), + HashSigns = ssl_handshake:available_signature_algs(SupportedHashSigns, Version, [Version]), + Msg = ssl_handshake:certificate_request(CipherSuite, CertDbHandle, CertDbRef, + HashSigns, Version), State = Connection:send_handshake(Msg, State0), State#state{client_certificate_requested = true}; @@ -1881,15 +1890,16 @@ make_premaster_secret({MajVer, MinVer}, rsa) -> make_premaster_secret(_, _) -> undefined. -negotiated_hashsign(undefined, Alg, Version) -> +negotiated_hashsign(undefined, KexAlg, PubKeyInfo, Version) -> %% Not negotiated choose default - case is_anonymous(Alg) of + case is_anonymous(KexAlg) of true -> {null, anon}; false -> - ssl_handshake:select_hashsign_algs(Alg, Version) + {PubAlg, _, _} = PubKeyInfo, + ssl_handshake:select_hashsign_algs(undefined, PubAlg, Version) end; -negotiated_hashsign(HashSign = {_, _}, _, _) -> +negotiated_hashsign(HashSign = {_, _}, _, _, _) -> HashSign. ssl_options_list(SslOptions) -> diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index e98073080a..644903cf4b 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -46,7 +46,7 @@ %% Handshake messages -export([hello_request/0, server_hello/4, server_hello_done/0, - certificate/4, certificate_request/4, key_exchange/3, + certificate/4, certificate_request/5, key_exchange/3, finished/5, next_protocol/1]). %% Handle handshake messages @@ -64,8 +64,8 @@ ]). %% Cipher suites handling --export([available_suites/2, cipher_suites/2, - select_session/10, supported_ecc/1]). +-export([available_suites/2, available_signature_algs/3, cipher_suites/2, + select_session/11, supported_ecc/1]). %% Extensions handling -export([client_hello_extensions/6, @@ -74,8 +74,8 @@ ]). %% MISC --export([select_version/3, prf/5, select_hashsign/3, - select_hashsign_algs/2, select_hashsign_algs/3, +-export([select_version/3, prf/5, select_hashsign/5, + select_hashsign_algs/3, premaster_secret/2, premaster_secret/3, premaster_secret/4]). %%==================================================================== @@ -120,7 +120,8 @@ server_hello(SessionId, Version, ConnectionStates, Extensions) -> server_hello_done() -> #server_hello_done{}. -client_hello_extensions(Host, Version, CipherSuites, SslOpts, ConnectionStates, Renegotiation) -> +client_hello_extensions(Host, Version, CipherSuites, + #ssl_options{signature_algs = SupportedHashSigns, versions = AllVersions} = SslOpts, ConnectionStates, Renegotiation) -> {EcPointFormats, EllipticCurves} = case advertises_ec_ciphers(lists:map(fun ssl_cipher:suite_definition/1, CipherSuites)) of true -> @@ -134,7 +135,7 @@ client_hello_extensions(Host, Version, CipherSuites, SslOpts, ConnectionStates, renegotiation_info = renegotiation_info(tls_record, client, ConnectionStates, Renegotiation), srp = SRP, - hash_signs = advertised_hash_signs(Version), + signature_algs = available_signature_algs(SupportedHashSigns, Version, AllVersions), ec_point_formats = EcPointFormats, elliptic_curves = EllipticCurves, alpn = encode_alpn(SslOpts#ssl_options.alpn_advertised_protocols, Renegotiation), @@ -203,14 +204,14 @@ client_certificate_verify(OwnCert, MasterSecret, Version, end. %%-------------------------------------------------------------------- --spec certificate_request(ssl_cipher:cipher_suite(), db_handle(), certdb_ref(), ssl_record:ssl_version()) -> - #certificate_request{}. +-spec certificate_request(ssl_cipher:cipher_suite(), db_handle(), + certdb_ref(), #hash_sign_algos{}, ssl_record:ssl_version()) -> + #certificate_request{}. %% %% Description: Creates a certificate_request message, called by the server. %%-------------------------------------------------------------------- -certificate_request(CipherSuite, CertDbHandle, CertDbRef, Version) -> +certificate_request(CipherSuite, CertDbHandle, CertDbRef, HashSigns, Version) -> Types = certificate_types(ssl_cipher:suite_definition(CipherSuite), Version), - HashSigns = advertised_hash_signs(Version), Authorities = certificate_authorities(CertDbHandle, CertDbRef), #certificate_request{ certificate_types = Types, @@ -351,6 +352,9 @@ verify_server_key(#server_key_params{params_bin = EncParams, %% %% Description: Checks that the certificate_verify message is valid. %%-------------------------------------------------------------------- +certificate_verify(_, _, _, undefined, _, _) -> + ?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE); + certificate_verify(Signature, PublicKeyInfo, Version, HashSign = {HashAlgo, _}, MasterSecret, {_, Handshake}) -> Hash = calc_certificate_verify(Version, HashAlgo, MasterSecret, Handshake), @@ -379,10 +383,11 @@ verify_signature(_Version, Hash, _HashAlgo, Signature, {?rsaEncryption, PubKey, end; verify_signature(_Version, Hash, {HashAlgo, dsa}, Signature, {?'id-dsa', PublicKey, PublicKeyParams}) -> public_key:verify({digest, Hash}, HashAlgo, Signature, {PublicKey, PublicKeyParams}); -verify_signature(_Version, Hash, {HashAlgo, ecdsa}, Signature, +verify_signature(_, Hash, {HashAlgo, _SignAlg}, Signature, {?'id-ecPublicKey', PublicKey, PublicKeyParams}) -> public_key:verify({digest, Hash}, HashAlgo, Signature, {PublicKey, PublicKeyParams}). + %%-------------------------------------------------------------------- -spec certify(#certificate{}, db_handle(), certdb_ref(), integer() | nolimit, verify_peer | verify_none, {fun(), term}, fun(), term(), term(), @@ -573,43 +578,46 @@ prf({3,_N}, Secret, Label, Seed, WantedLength) -> %%-------------------------------------------------------------------- --spec select_hashsign(#hash_sign_algos{}| undefined, undefined | binary(), ssl_record:ssl_version()) -> - {atom(), atom()} | undefined. +-spec select_hashsign(#hash_sign_algos{} | undefined, undefined | binary(), + atom(), [atom()], ssl_record:ssl_version()) -> + {atom(), atom()} | undefined | #alert{}. %% -%% Description: +%% Description: Handles signature_algorithms extension %%-------------------------------------------------------------------- -select_hashsign(_, undefined, _Version) -> +select_hashsign(_, undefined, _, _, _Version) -> {null, anon}; %% The signature_algorithms extension was introduced with TLS 1.2. Ignore it if we have %% negotiated a lower version. -select_hashsign(#hash_sign_algos{hash_sign_algos = HashSigns}, Cert, {Major, Minor} = Version) - when Major >= 3 andalso Minor >= 3 -> - #'OTPCertificate'{tbsCertificate = TBSCert} =public_key:pkix_decode_cert(Cert, otp), +select_hashsign(HashSigns, Cert, KeyExAlgo, + undefined, {Major, Minor} = Version) when Major >= 3 andalso Minor >= 3-> + select_hashsign(HashSigns, Cert, KeyExAlgo, tls_v1:default_signature_algs(Version), Version); +select_hashsign(#hash_sign_algos{hash_sign_algos = HashSigns}, Cert, KeyExAlgo, SupportedHashSigns, + {Major, Minor}) when Major >= 3 andalso Minor >= 3 -> + #'OTPCertificate'{tbsCertificate = TBSCert} = public_key:pkix_decode_cert(Cert, otp), #'OTPSubjectPublicKeyInfo'{algorithm = {_,Algo, _}} = TBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo, - DefaultHashSign = {_, Sign} = select_hashsign_algs(undefined, Algo, Version), - case lists:filter(fun({sha, dsa}) -> + Sign = cert_sign(Algo), + case lists:filter(fun({sha, dsa = S}) when S == Sign -> true; ({_, dsa}) -> false; - ({Hash, S}) when S == Sign -> - ssl_cipher:is_acceptable_hash(Hash, - proplists:get_value(hashs, crypto:supports())); + ({_, _} = Algos) -> + is_acceptable_hash_sign(Algos, Sign, KeyExAlgo, SupportedHashSigns); (_) -> false end, HashSigns) of [] -> - DefaultHashSign; - [HashSign| _] -> + ?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY); + [HashSign | _] -> HashSign end; -select_hashsign(_, Cert, Version) -> +select_hashsign(_, Cert, _, _, Version) -> #'OTPCertificate'{tbsCertificate = TBSCert} = public_key:pkix_decode_cert(Cert, otp), #'OTPSubjectPublicKeyInfo'{algorithm = {_,Algo, _}} = TBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo, select_hashsign_algs(undefined, Algo, Version). %%-------------------------------------------------------------------- --spec select_hashsign_algs(#hash_sign_algos{}| undefined, oid(), ssl_record:ssl_version()) -> +-spec select_hashsign_algs({atom(), atom()}| undefined, oid(), ssl_record:ssl_version()) -> {atom(), atom()}. %% Description: For TLS 1.2 hash function and signature algorithm pairs can be @@ -642,24 +650,6 @@ select_hashsign_algs(undefined, ?rsaEncryption, _) -> select_hashsign_algs(undefined, ?'id-dsa', _) -> {sha, dsa}. --spec select_hashsign_algs(atom(), ssl_record:ssl_version()) -> {atom(), atom()}. -%% Wrap function to keep the knowledge of the default values in -%% one place only -select_hashsign_algs(Alg, Version) when (Alg == rsa orelse - Alg == dhe_rsa orelse - Alg == dh_rsa orelse - Alg == ecdhe_rsa orelse - Alg == ecdh_rsa orelse - Alg == srp_rsa) -> - select_hashsign_algs(undefined, ?rsaEncryption, Version); -select_hashsign_algs(Alg, Version) when (Alg == dhe_dss orelse - Alg == dh_dss orelse - Alg == srp_dss) -> - select_hashsign_algs(undefined, ?'id-dsa', Version); -select_hashsign_algs(Alg, Version) when (Alg == ecdhe_ecdsa orelse - Alg == ecdh_ecdsa) -> - select_hashsign_algs(undefined, ?'id-ecPublicKey', Version). - %%-------------------------------------------------------------------- -spec master_secret(atom(), ssl_record:ssl_version(), #session{} | binary(), #connection_states{}, client | server) -> {binary(), #connection_states{}} | #alert{}. @@ -1063,9 +1053,56 @@ available_suites(UserSuites, Version) -> lists:member(Suite, ssl_cipher:all_suites(Version)) end, UserSuites). -available_suites(ServerCert, UserSuites, Version, Curve) -> +available_suites(ServerCert, UserSuites, Version, undefined, Curve) -> ssl_cipher:filter(ServerCert, available_suites(UserSuites, Version)) - -- unavailable_ecc_suites(Curve). + -- unavailable_ecc_suites(Curve); +available_suites(ServerCert, UserSuites, Version, HashSigns, Curve) -> + Suites = available_suites(ServerCert, UserSuites, Version, undefined, Curve), + filter_hashsigns(Suites, [ssl_cipher:suite_definition(Suite) || Suite <- Suites], HashSigns, []). +filter_hashsigns([], [], _, Acc) -> + lists:reverse(Acc); +filter_hashsigns([Suite | Suites], [{KeyExchange,_,_,_} | Algos], HashSigns, + Acc) when KeyExchange == dhe_ecdsa; + KeyExchange == ecdhe_ecdsa -> + do_filter_hashsigns(ecdsa, Suite, Suites, Algos, HashSigns, Acc); + +filter_hashsigns([Suite | Suites], [{KeyExchange,_,_,_} | Algos], HashSigns, + Acc) when KeyExchange == rsa; + KeyExchange == dhe_rsa; + KeyExchange == ecdhe_rsa; + KeyExchange == srp_rsa; + KeyExchange == rsa_psk -> + do_filter_hashsigns(rsa, Suite, Suites, Algos, HashSigns, Acc); +filter_hashsigns([Suite | Suites], [{KeyExchange,_,_,_} | Algos], HashSigns, Acc) when + KeyExchange == dhe_dss; + KeyExchange == srp_dss -> + do_filter_hashsigns(dsa, Suite, Suites, Algos, HashSigns, Acc); +filter_hashsigns([Suite | Suites], [{KeyExchange,_,_,_} | Algos], HashSigns, Acc) when + KeyExchange == dh_dss; + KeyExchange == dh_rsa; + KeyExchange == dh_ecdsa; + KeyExchange == ecdh_rsa; + KeyExchange == ecdh_ecdsa -> + %% Fixed DH certificates MAY be signed with any hash/signature + %% algorithm pair appearing in the hash_sign extension. The names + %% DH_DSS, DH_RSA, ECDH_ECDSA, and ECDH_RSA are historical. + filter_hashsigns(Suites, Algos, HashSigns, [Suite| Acc]); +filter_hashsigns([Suite | Suites], [{KeyExchange,_,_,_} | Algos], HashSigns, Acc) when + KeyExchange == dh_anon; + KeyExchange == ecdh_anon; + KeyExchange == srp_anon; + KeyExchange == psk; + KeyExchange == dhe_psk -> + %% In this case hashsigns is not used as the kexchange is anonaymous + filter_hashsigns(Suites, Algos, HashSigns, [Suite| Acc]). + +do_filter_hashsigns(SignAlgo, Suite, Suites, Algos, HashSigns, Acc) -> + case lists:keymember(SignAlgo, 2, HashSigns) of + true -> + filter_hashsigns(Suites, Algos, HashSigns, [Suite| Acc]); + false -> + filter_hashsigns(Suites, Algos, HashSigns, Acc) + end. unavailable_ecc_suites(no_curve) -> ssl_cipher:ec_keyed_suites(); @@ -1077,17 +1114,17 @@ cipher_suites(Suites, false) -> cipher_suites(Suites, true) -> Suites. -select_session(SuggestedSessionId, CipherSuites, Compressions, Port, #session{ecc = ECCCurve} = +select_session(SuggestedSessionId, CipherSuites, HashSigns, Compressions, Port, #session{ecc = ECCCurve} = Session, Version, - #ssl_options{ciphers = UserSuites, honor_cipher_order = HCO} = SslOpts, + #ssl_options{ciphers = UserSuites, honor_cipher_order = HonorCipherOrder} = SslOpts, Cache, CacheCb, Cert) -> {SessionId, Resumed} = ssl_session:server_id(Port, SuggestedSessionId, SslOpts, Cert, Cache, CacheCb), case Resumed of undefined -> - Suites = available_suites(Cert, UserSuites, Version, ECCCurve), - CipherSuite = select_cipher_suite(CipherSuites, Suites, HCO), + Suites = available_suites(Cert, UserSuites, Version, HashSigns, ECCCurve), + CipherSuite = select_cipher_suite(CipherSuites, Suites, HonorCipherOrder), Compression = select_compression(Compressions), {new, Session#session{session_id = SessionId, cipher_suite = CipherSuite, @@ -1155,7 +1192,7 @@ handle_client_hello_extensions(RecordCB, Random, ClientCipherSuites, #hello_extensions{renegotiation_info = Info, srp = SRP, ec_point_formats = ECCFormat, - alpn = ALPN, + alpn = ALPN, next_protocol_negotiation = NextProtocolNegotiation}, Version, #ssl_options{secure_renegotiate = SecureRenegotation, alpn_preferred_protocols = ALPNPreferredProtocols} = Opts, @@ -1324,7 +1361,7 @@ handle_renegotiation_info(_RecordCB, ConnectionStates, SecureRenegotation) -> hello_extensions_list(#hello_extensions{renegotiation_info = RenegotiationInfo, srp = SRP, - hash_signs = HashSigns, + signature_algs = HashSigns, ec_point_formats = EcPointFormats, elliptic_curves = EllipticCurves, alpn = ALPN, @@ -1799,7 +1836,7 @@ dec_hello_extensions(<<?UINT16(?SIGNATURE_ALGORITHMS_EXT), ?UINT16(Len), <<?UINT16(SignAlgoListLen), SignAlgoList/binary>> = ExtData, HashSignAlgos = [{ssl_cipher:hash_algorithm(Hash), ssl_cipher:sign_algorithm(Sign)} || <<?BYTE(Hash), ?BYTE(Sign)>> <= SignAlgoList], - dec_hello_extensions(Rest, Acc#hello_extensions{hash_signs = + dec_hello_extensions(Rest, Acc#hello_extensions{signature_algs = #hash_sign_algos{hash_sign_algos = HashSignAlgos}}); dec_hello_extensions(<<?UINT16(?ELLIPTIC_CURVES_EXT), ?UINT16(Len), @@ -1899,7 +1936,7 @@ from_2bytes(<<?UINT16(N), Rest/binary>>, Acc) -> key_exchange_alg(rsa) -> ?KEY_EXCHANGE_RSA; key_exchange_alg(Alg) when Alg == dhe_rsa; Alg == dhe_dss; - Alg == dh_dss; Alg == dh_rsa; Alg == dh_anon -> + Alg == dh_dss; Alg == dh_rsa; Alg == dh_anon -> ?KEY_EXCHANGE_DIFFIE_HELLMAN; key_exchange_alg(Alg) when Alg == ecdhe_rsa; Alg == ecdh_rsa; Alg == ecdhe_ecdsa; Alg == ecdh_ecdsa; @@ -2008,27 +2045,16 @@ is_member(Suite, SupportedSuites) -> select_compression(_CompressionMetodes) -> ?NULL. --define(TLSEXT_SIGALG_RSA(MD), {MD, rsa}). --define(TLSEXT_SIGALG_DSA(MD), {MD, dsa}). --define(TLSEXT_SIGALG_ECDSA(MD), {MD, ecdsa}). - --define(TLSEXT_SIGALG(MD), ?TLSEXT_SIGALG_ECDSA(MD), ?TLSEXT_SIGALG_RSA(MD)). - -advertised_hash_signs({Major, Minor}) when Major >= 3 andalso Minor >= 3 -> - HashSigns = [?TLSEXT_SIGALG(sha512), - ?TLSEXT_SIGALG(sha384), - ?TLSEXT_SIGALG(sha256), - ?TLSEXT_SIGALG(sha224), - ?TLSEXT_SIGALG(sha), - ?TLSEXT_SIGALG_DSA(sha), - ?TLSEXT_SIGALG_RSA(md5)], - CryptoSupport = crypto:supports(), - HasECC = proplists:get_bool(ecdsa, proplists:get_value(public_keys, CryptoSupport)), - Hashs = proplists:get_value(hashs, CryptoSupport), - #hash_sign_algos{hash_sign_algos = - lists:filter(fun({Hash, ecdsa}) -> HasECC andalso proplists:get_bool(Hash, Hashs); - ({Hash, _}) -> proplists:get_bool(Hash, Hashs) end, HashSigns)}; -advertised_hash_signs(_) -> +available_signature_algs(undefined, _, _) -> + undefined; +available_signature_algs(SupportedHashSigns, {Major, Minor}, AllVersions) when Major >= 3 andalso Minor >= 3 -> + case tls_record:lowest_protocol_version(AllVersions) of + {3, 3} -> + #hash_sign_algos{hash_sign_algos = SupportedHashSigns}; + _ -> + undefined + end; +available_signature_algs(_, _, _) -> undefined. psk_secret(PSKIdentity, PSKLookup) -> @@ -2123,3 +2149,25 @@ distpoints_lookup([DistPoint | Rest], Callback, CRLDbHandle) -> CRLs -> [{DistPoint, {CRL, public_key:der_decode('CertificateList', CRL)}} || CRL <- CRLs] end. + +cert_sign(?rsaEncryption) -> + rsa; +cert_sign(?'id-ecPublicKey') -> + ecdsa; +cert_sign(?'id-dsa') -> + dsa; +cert_sign(Alg) -> + {_, Sign} =public_key:pkix_sign_types(Alg), + Sign. + +is_acceptable_hash_sign({_, Sign} = Algos, Sign, _, SupportedHashSigns) -> + is_acceptable_hash_sign(Algos, SupportedHashSigns); +is_acceptable_hash_sign(Algos,_, KeyExAlgo, SupportedHashSigns) when KeyExAlgo == dh_ecdsa; + KeyExAlgo == ecdh_rsa; + KeyExAlgo == ecdh_ecdsa -> + is_acceptable_hash_sign(Algos, SupportedHashSigns); +is_acceptable_hash_sign(_,_,_,_) -> + false. +is_acceptable_hash_sign(Algos, SupportedHashSigns) -> + lists:member(Algos, SupportedHashSigns). + diff --git a/lib/ssl/src/ssl_handshake.hrl b/lib/ssl/src/ssl_handshake.hrl index 58b4d5a23d..b74a65939b 100644 --- a/lib/ssl/src/ssl_handshake.hrl +++ b/lib/ssl/src/ssl_handshake.hrl @@ -95,7 +95,7 @@ -record(hello_extensions, { renegotiation_info, - hash_signs, % supported combinations of hashes/signature algos + signature_algs, % supported combinations of hashes/signature algos alpn, next_protocol_negotiation = undefined, % [binary()] srp, diff --git a/lib/ssl/src/ssl_internal.hrl b/lib/ssl/src/ssl_internal.hrl index 913746598f..9c52f5a315 100644 --- a/lib/ssl/src/ssl_internal.hrl +++ b/lib/ssl/src/ssl_internal.hrl @@ -135,7 +135,8 @@ padding_check = true :: boolean(), fallback = false :: boolean(), crl_check :: boolean() | peer | best_effort, - crl_cache + crl_cache, + signature_algs }). -record(socket_options, diff --git a/lib/ssl/src/ssl_tls_dist_proxy.erl b/lib/ssl/src/ssl_tls_dist_proxy.erl index 4c789793ec..8a39bde255 100644 --- a/lib/ssl/src/ssl_tls_dist_proxy.erl +++ b/lib/ssl/src/ssl_tls_dist_proxy.erl @@ -195,6 +195,11 @@ accept_loop(Proxy, erts = Type, Listen, Extra) -> {_Kernel, unsupported_protocol} -> exit(unsupported_protocol) end; + {error, closed} -> + %% The listening socket is closed: the proxy process is + %% shutting down. Exit normally, to avoid generating a + %% spurious error report. + exit(normal); Error -> exit(Error) end, diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl index c3f0206d25..93716d31b8 100644 --- a/lib/ssl/src/tls_connection.erl +++ b/lib/ssl/src/tls_connection.erl @@ -182,8 +182,7 @@ hello(start, #state{host = Host, port = Port, role = client, next_state(hello, hello, Record, State); hello(Hello = #client_hello{client_version = ClientVersion, - extensions = #hello_extensions{hash_signs = HashSigns, - ec_point_formats = EcPointFormats, + extensions = #hello_extensions{ec_point_formats = EcPointFormats, elliptic_curves = EllipticCurves}}, State = #state{connection_states = ConnectionStates0, port = Port, session = #session{own_certificate = Cert} = Session0, @@ -191,27 +190,28 @@ hello(Hello = #client_hello{client_version = ClientVersion, session_cache = Cache, session_cache_cb = CacheCb, negotiated_protocol = CurrentProtocol, + key_algorithm = KeyExAlg, ssl_options = SslOpts}) -> + case tls_handshake:hello(Hello, SslOpts, {Port, Session0, Cache, CacheCb, - ConnectionStates0, Cert}, Renegotiation) of + ConnectionStates0, Cert, KeyExAlg}, Renegotiation) of #alert{} = Alert -> handle_own_alert(Alert, ClientVersion, hello, State); {Version, {Type, Session}, - ConnectionStates, Protocol0, ServerHelloExt} -> - + ConnectionStates, Protocol0, ServerHelloExt, HashSign} -> Protocol = case Protocol0 of - undefined -> CurrentProtocol; - _ -> Protocol0 - end, - - HashSign = ssl_handshake:select_hashsign(HashSigns, Cert, Version), - ssl_connection:hello({common_client_hello, Type, ServerHelloExt, HashSign}, + undefined -> CurrentProtocol; + _ -> Protocol0 + end, + ssl_connection:hello({common_client_hello, Type, ServerHelloExt}, State#state{connection_states = ConnectionStates, negotiated_version = Version, + hashsign_algorithm = HashSign, session = Session, client_ecc = {EllipticCurves, EcPointFormats}, negotiated_protocol = Protocol}, ?MODULE) end; + hello(Hello = #server_hello{}, #state{connection_states = ConnectionStates0, negotiated_version = ReqVersion, @@ -1069,3 +1069,4 @@ handle_sni_extension(#client_hello{extensions = HelloExtensions}, State0) -> end; handle_sni_extension(_, State0) -> State0. + diff --git a/lib/ssl/src/tls_handshake.erl b/lib/ssl/src/tls_handshake.erl index 0a6cb9f92d..ef718c13df 100644 --- a/lib/ssl/src/tls_handshake.erl +++ b/lib/ssl/src/tls_handshake.erl @@ -56,7 +56,7 @@ client_hello(Host, Port, ConnectionStates, Version = tls_record:highest_protocol_version(Versions), Pending = ssl_record:pending_connection_state(ConnectionStates, read), SecParams = Pending#connection_state.security_parameters, - AvailableCipherSuites = ssl_handshake:available_suites(UserSuites, Version), + AvailableCipherSuites = ssl_handshake:available_suites(UserSuites, Version), Extensions = ssl_handshake:client_hello_extensions(Host, Version, AvailableCipherSuites, SslOpts, ConnectionStates, Renegotiation), @@ -80,13 +80,13 @@ client_hello(Host, Port, ConnectionStates, -spec hello(#server_hello{} | #client_hello{}, #ssl_options{}, #connection_states{} | {inet:port_number(), #session{}, db_handle(), atom(), #connection_states{}, - binary() | undefined}, + binary() | undefined, ssl_cipher:key_algo()}, boolean()) -> {tls_record:tls_version(), session_id(), #connection_states{}, alpn | npn, binary() | undefined}| {tls_record:tls_version(), {resumed | new, #session{}}, #connection_states{}, binary() | undefined, - #hello_extensions{}} | + #hello_extensions{}, {ssl_cipher:hash(), ssl_cipher:sign_algo()} | undefined} | #alert{}. %% %% Description: Handles a recieved hello message @@ -149,26 +149,35 @@ get_tls_handshake(Version, Data, Buffer) -> %%% Internal functions %%-------------------------------------------------------------------- handle_client_hello(Version, #client_hello{session_id = SugesstedId, - cipher_suites = CipherSuites, - compression_methods = Compressions, - random = Random, - extensions = #hello_extensions{elliptic_curves = Curves} = HelloExt}, - #ssl_options{versions = Versions} = SslOpts, - {Port, Session0, Cache, CacheCb, ConnectionStates0, Cert}, Renegotiation) -> + cipher_suites = CipherSuites, + compression_methods = Compressions, + random = Random, + extensions = #hello_extensions{elliptic_curves = Curves, + signature_algs = ClientHashSigns} = HelloExt}, + #ssl_options{versions = Versions, + signature_algs = SupportedHashSigns} = SslOpts, + {Port, Session0, Cache, CacheCb, ConnectionStates0, Cert, _}, Renegotiation) -> case tls_record:is_acceptable_version(Version, Versions) of true -> + AvailableHashSigns = available_signature_algs(ClientHashSigns, SupportedHashSigns, Cert, Version), ECCCurve = ssl_handshake:select_curve(Curves, ssl_handshake:supported_ecc(Version)), {Type, #session{cipher_suite = CipherSuite} = Session1} - = ssl_handshake:select_session(SugesstedId, CipherSuites, Compressions, + = ssl_handshake:select_session(SugesstedId, CipherSuites, AvailableHashSigns, Compressions, Port, Session0#session{ecc = ECCCurve}, Version, SslOpts, Cache, CacheCb, Cert), case CipherSuite of no_suite -> ?ALERT_REC(?FATAL, ?INSUFFICIENT_SECURITY); _ -> - handle_client_hello_extensions(Version, Type, Random, CipherSuites, HelloExt, - SslOpts, Session1, ConnectionStates0, - Renegotiation) + {KeyExAlg,_,_,_} = ssl_cipher:suite_definition(CipherSuite), + case ssl_handshake:select_hashsign(ClientHashSigns, Cert, KeyExAlg, SupportedHashSigns, Version) of + #alert{} = Alert -> + Alert; + HashSign -> + handle_client_hello_extensions(Version, Type, Random, CipherSuites, HelloExt, + SslOpts, Session1, ConnectionStates0, + Renegotiation, HashSign) + end end; false -> ?ALERT_REC(?FATAL, ?PROTOCOL_VERSION) @@ -245,14 +254,14 @@ enc_handshake(HandshakeMsg, Version) -> handle_client_hello_extensions(Version, Type, Random, CipherSuites, - HelloExt, SslOpts, Session0, ConnectionStates0, Renegotiation) -> + HelloExt, SslOpts, Session0, ConnectionStates0, Renegotiation, HashSign) -> try ssl_handshake:handle_client_hello_extensions(tls_record, Random, CipherSuites, HelloExt, Version, SslOpts, Session0, ConnectionStates0, Renegotiation) of #alert{} = Alert -> Alert; {Session, ConnectionStates, Protocol, ServerHelloExt} -> - {Version, {Type, Session}, ConnectionStates, Protocol, ServerHelloExt} + {Version, {Type, Session}, ConnectionStates, Protocol, ServerHelloExt, HashSign} catch throw:Alert -> Alert end. @@ -269,3 +278,12 @@ handle_server_hello_extensions(Version, SessionId, Random, CipherSuite, {Version, SessionId, ConnectionStates, ProtoExt, Protocol} end. +available_signature_algs(undefined, SupportedHashSigns, _, {Major, Minor}) when (Major < 3) andalso (Minor < 3) -> + SupportedHashSigns; +available_signature_algs(#hash_sign_algos{hash_sign_algos = ClientHashSigns}, SupportedHashSigns, + _, {Major, Minor}) when (Major < 3) andalso (Minor < 3) -> + ordsets:intersection(ClientHashSigns, SupportedHashSigns); +available_signature_algs(_, _, _, _) -> + undefined. + + diff --git a/lib/ssl/src/tls_v1.erl b/lib/ssl/src/tls_v1.erl index 09e378cfeb..03cef633d5 100644 --- a/lib/ssl/src/tls_v1.erl +++ b/lib/ssl/src/tls_v1.erl @@ -31,7 +31,8 @@ -export([master_secret/4, finished/5, certificate_verify/3, mac_hash/7, setup_keys/8, suites/1, prf/5, - ecc_curves/1, oid_to_enum/1, enum_to_oid/1]). + ecc_curves/1, oid_to_enum/1, enum_to_oid/1, + default_signature_algs/1, signature_algs/2]). %%==================================================================== %% Internal application API @@ -256,6 +257,52 @@ suites(3) -> ] ++ suites(2). + +signature_algs({3, 3}, HashSigns) -> + CryptoSupports = crypto:supports(), + Hashes = proplists:get_value(hashs, CryptoSupports), + PubKeys = proplists:get_value(public_keys, CryptoSupports), + Supported = lists:foldl(fun({Hash, dsa = Sign} = Alg, Acc) -> + case proplists:get_bool(dss, PubKeys) + andalso proplists:get_bool(Hash, Hashes) + andalso is_pair(Hash, Sign, Hashes) + of + true -> + [Alg | Acc]; + false -> + Acc + end; + ({Hash, Sign} = Alg, Acc) -> + case proplists:get_bool(Sign, PubKeys) + andalso proplists:get_bool(Hash, Hashes) + andalso is_pair(Hash, Sign, Hashes) + of + true -> + [Alg | Acc]; + false -> + Acc + end + end, [], HashSigns), + lists:reverse(Supported). + +default_signature_algs({3, 3} = Version) -> + Default = [%% SHA2 + {sha512, ecdsa}, + {sha512, rsa}, + {sha384, ecdsa}, + {sha384, rsa}, + {sha256, ecdsa}, + {sha256, rsa}, + {sha224, ecdsa}, + {sha224, rsa}, + %% SHA + {sha, ecdsa}, + {sha, rsa}, + {sha, dsa}], + signature_algs(Version, Default); +default_signature_algs(_) -> + undefined. + %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- @@ -340,6 +387,17 @@ finished_label(client) -> finished_label(server) -> <<"server finished">>. +is_pair(sha, dsa, _) -> + true; +is_pair(_, dsa, _) -> + false; +is_pair(Hash, ecdsa, Hashs) -> + AtLeastSha = Hashs -- [md2,md4,md5], + lists:member(Hash, AtLeastSha); +is_pair(Hash, rsa, Hashs) -> + AtLeastMd5 = Hashs -- [md2,md4], + lists:member(Hash, AtLeastMd5). + %% list ECC curves in prefered order ecc_curves(_Minor) -> TLSCurves = [sect571r1,sect571k1,secp521r1,brainpoolP512r1, diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index f2cf99e8a8..f045d50cce 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -58,7 +58,7 @@ all() -> groups() -> [{basic, [], basic_tests()}, {options, [], options_tests()}, - {'tlsv1.2', [], all_versions_groups()}, + {'tlsv1.2', [], all_versions_groups() ++ [conf_signature_algs, no_common_signature_algs]}, {'tlsv1.1', [], all_versions_groups()}, {'tlsv1', [], all_versions_groups() ++ rizzo_tests()}, {'sslv3', [], all_versions_groups() ++ rizzo_tests() ++ [ciphersuite_vs_version]}, @@ -2900,7 +2900,61 @@ ciphersuite_vs_version(Config) when is_list(Config) -> _ -> ct:fail({unexpected_server_hello, ServerHello}) end. - + +%%-------------------------------------------------------------------- +conf_signature_algs() -> + [{doc,"Test to set the signature_algs option on both client and server"}]. +conf_signature_algs(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = + ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, send_recv_result, []}}, + {options, [{active, false}, {signature_algs, [{sha256, rsa}]} | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = + ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, send_recv_result, []}}, + {options, [{active, false}, {signature_algs, [{sha256, rsa}]} | ClientOpts]}]), + + ct:log("Testcase ~p, Client ~p Server ~p ~n", + [self(), Client, Server]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + + +%%-------------------------------------------------------------------- +no_common_signature_algs() -> + [{doc,"Set the signature_algs option so that there client and server does not share any hash sign algorithms"}]. +no_common_signature_algs(Config) when is_list(Config) -> + + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + + Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, + {from, self()}, + {options, [{signature_algs, [{sha256, rsa}]} + | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {options, [{signature_algs, [{sha384, rsa}]} + | ClientOpts]}]), + + ssl_test_lib:check_result(Server, {error, {tls_alert, "insufficient security"}}, + Client, {error, {tls_alert, "insufficient security"}}). + %%-------------------------------------------------------------------- dont_crash_on_handshake_garbage() -> diff --git a/lib/ssl/test/ssl_handshake_SUITE.erl b/lib/ssl/test/ssl_handshake_SUITE.erl index b0bb77c598..d050812208 100644 --- a/lib/ssl/test/ssl_handshake_SUITE.erl +++ b/lib/ssl/test/ssl_handshake_SUITE.erl @@ -166,10 +166,10 @@ ignore_hassign_extension_pre_tls_1_2(Config) -> CertFile = proplists:get_value(certfile, Opts), [{_, Cert, _}] = ssl_test_lib:pem_to_der(CertFile), HashSigns = #hash_sign_algos{hash_sign_algos = [{sha512, rsa}, {sha, dsa}]}, - {sha512, rsa} = ssl_handshake:select_hashsign(HashSigns, Cert, {3,3}), + {sha512, rsa} = ssl_handshake:select_hashsign(HashSigns, Cert, ecdhe_rsa, tls_v1:default_signature_algs({3,3}), {3,3}), %%% Ignore - {md5sha, rsa} = ssl_handshake:select_hashsign(HashSigns, Cert, {3,2}), - {md5sha, rsa} = ssl_handshake:select_hashsign(HashSigns, Cert, {3,0}). + {md5sha, rsa} = ssl_handshake:select_hashsign(HashSigns, Cert, ecdhe_rsa, tls_v1:default_signature_algs({3,2}), {3,2}), + {md5sha, rsa} = ssl_handshake:select_hashsign(HashSigns, Cert, ecdhe_rsa, tls_v1:default_signature_algs({3,0}), {3,0}). is_supported(Hash) -> Algos = crypto:supports(), diff --git a/lib/stdlib/test/error_logger_h_SUITE.erl b/lib/stdlib/test/error_logger_h_SUITE.erl index 30811f3fb4..9828a075cc 100644 --- a/lib/stdlib/test/error_logger_h_SUITE.erl +++ b/lib/stdlib/test/error_logger_h_SUITE.erl @@ -65,11 +65,18 @@ logfile(Config) -> error_logger:logfile(close), analyse_events(Log, Ev, [AtNode], unlimited), - [] = [{X, file:pid2name(X)} || X <- processes(), Data <- [process_info(X, [current_function])], - Data =/= undefined, - element(1, element(2, lists:keyfind(current_function, 1, Data))) - =:= file_io_server, - file:pid2name(X) =:= {ok, Log}], + %% Make sure that the file_io_server process has been stopped + [] = lists:filtermap( + fun(X) -> + case {process_info(X, [current_function]), + file:pid2name(X)} of + {[{current_function, {file_io_server, _, _}}], + {ok,P2N = Log}} -> + {true, {X, P2N}}; + _ -> + false + end + end, processes()), test_server:stop_node(Node), @@ -112,7 +119,7 @@ tty(Config) -> do_one_tty(Log, Ev, unlimited), Pa = "-pa " ++ filename:dirname(code:which(?MODULE)), - {ok,Node} = start_node(logfile, Pa), + {ok,Node} = start_node(tty, Pa), tty_log_open(Log), ok = rpc:call(Node, erlang, apply, [fun gen_events/1,[Ev]]), tty_log_close(), |