/*
* Copyright ( c ) 2016 , 2022 , Oracle and / or its affiliates . All rights reserved .
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER .
*
* This code is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License version 2 only , as
* published by the Free Software Foundation .
*
* This code is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License
* version 2 for more details ( a copy is included in the LICENSE file that
* accompanied this code ) .
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work ; if not , write to the Free Software Foundation ,
* Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA .
*
* Please contact Oracle , 500 Oracle Parkway , Redwood Shores , CA 94065 USA
* or visit www . oracle . com if you need additional information or have any
* questions .
*/
#include "precompiled.hpp"
#include "jvm.h"
#include "unittest.hpp"
#include "runtime/arguments.hpp"
#include "runtime/flags/jvmFlag.hpp"
#include "utilities/align.hpp"
#include "utilities/globalDefinitions.hpp"
#include <errno.h>
class ArgumentsTest :
public ::testing::Test {
public :
static intx parse_xss_inner_annotated(
const char * str, jint expected_err,
const char * fil
e, int line_number);
// Expose the private Arguments functions.
static Arguments::ArgsRange check_memory_size(julong size, julong min_size, julong max_size) {
return Arguments::check_memory_size(size, min_size, max_size);
}
static jint parse_xss(const JavaVMOption* option, const char * tail, intx* out_ThreadStackSize) {
return Arguments::parse_xss(option, tail, out_ThreadStackSize);
}
static bool parse_argument(const char * name, const char * value) {
char buf[1024 ];
int ret = jio_snprintf(buf, sizeof (buf), "%s=%s" , name, value);
if (ret > 0 ) {
return Arguments::parse_argument(buf, JVMFlagOrigin::COMMAND_LINE);
} else {
return false ;
}
}
};
TEST_F(ArgumentsTest, atojulong) {
char ullong_max[32 ];
int ret = jio_snprintf(ullong_max, sizeof (ullong_max), JULONG_FORMAT, ULLONG_MAX);
ASSERT_NE(-1 , ret);
julong value;
const char * invalid_strings[] = {
"" , "-1" , "-100" , " 1" , "2 " , "3 2" , "1.0" ,
"0x4.5" , "0x" , "0x0x1" "0.001" , "4e10" , "e"
"K" , "M" , "G" , "1MB" , "1KM" , "AA" , "0B" ,
"18446744073709551615K" , "17179869184G" ,
"999999999999999999999999999999"
};
for (uint i = 0 ; i < ARRAY_SIZE(invalid_strings); i++) {
ASSERT_FALSE(Arguments::atojulong(invalid_strings[i], &value))
<< "Invalid string '" << invalid_strings[i] << "' parsed without error." ;
}
struct {
const char * str;
julong expected_value;
} valid_strings[] = {
{ "0" , 0 },
{ "4711" , 4711 },
{ "1K" , 1 ULL * K },
{ "1k" , 1 ULL * K },
{ "2M" , 2 ULL * M },
{ "2m" , 2 ULL * M },
{ "4G" , 4 ULL * G },
{ "4g" , 4 ULL * G },
{ "0K" , 0 },
{ ullong_max, ULLONG_MAX },
{ "0xcafebabe" , 0 xcafebabe },
{ "0XCAFEBABE" , 0 xcafebabe },
{ "0XCAFEbabe" , 0 xcafebabe },
{ "0x10K" , 0 x10 * K }
};
for (uint i = 0 ; i < ARRAY_SIZE(valid_strings); i++) {
ASSERT_TRUE(Arguments::atojulong(valid_strings[i].str, &value))
<< "Valid string '" << valid_strings[i].str << "' did not parse." ;
ASSERT_EQ(valid_strings[i].expected_value, value);
}
}
TEST_F(ArgumentsTest, check_memory_size__min) {
EXPECT_EQ(check_memory_size(999 , 1000 , max_uintx), Arguments::arg_too_small);
EXPECT_EQ(check_memory_size(1000 , 1000 , max_uintx), Arguments::arg_in_range);
EXPECT_EQ(check_memory_size(1001 , 1000 , max_uintx), Arguments::arg_in_range);
EXPECT_EQ(check_memory_size(max_intx - 2 , max_intx - 1 , max_uintx), Arguments::arg_too_small);
EXPECT_EQ(check_memory_size(max_intx - 1 , max_intx - 1 , max_uintx), Arguments::arg_in_range);
EXPECT_EQ(check_memory_size(max_intx - 0 , max_intx - 1 , max_uintx), Arguments::arg_in_range);
EXPECT_EQ(check_memory_size(max_intx - 1 , max_intx, max_uintx), Arguments::arg_too_small);
EXPECT_EQ(check_memory_size(max_intx , max_intx, max_uintx), Arguments::arg_in_range);
NOT_LP64(
EXPECT_EQ(check_memory_size((julong)max_intx + 1 , max_intx, max_uintx), Arguments::arg_in_range);
EXPECT_EQ(check_memory_size( max_intx - 1 , (julong)max_intx + 1 , max_uintx), Arguments::arg_too_small);
EXPECT_EQ(check_memory_size( max_intx , (julong)max_intx + 1 , max_uintx), Arguments::arg_too_small);
EXPECT_EQ(check_memory_size((julong)max_intx + 1 , (julong)max_intx + 1 , max_uintx), Arguments::arg_in_range);
EXPECT_EQ(check_memory_size((julong)max_intx + 2 , (julong)max_intx + 1 , max_uintx), Arguments::arg_in_range);
);
EXPECT_EQ(check_memory_size(max_uintx - 2 , max_uintx - 1 , max_uintx), Arguments::arg_too_small);
EXPECT_EQ(check_memory_size(max_uintx - 1 , max_uintx - 1 , max_uintx), Arguments::arg_in_range);
EXPECT_EQ(check_memory_size(max_uintx , max_uintx - 1 , max_uintx), Arguments::arg_in_range);
EXPECT_EQ(check_memory_size(max_uintx - 1 , max_uintx, max_uintx), Arguments::arg_too_small);
EXPECT_EQ(check_memory_size(max_uintx , max_uintx, max_uintx), Arguments::arg_in_range);
}
TEST_F(ArgumentsTest, check_memory_size__max) {
EXPECT_EQ(check_memory_size(max_uintx - 1 , 1000 , max_uintx), Arguments::arg_in_range);
EXPECT_EQ(check_memory_size(max_uintx , 1000 , max_uintx), Arguments::arg_in_range);
EXPECT_EQ(check_memory_size(max_intx - 2 , 1000 , max_intx - 1 ), Arguments::arg_in_range);
EXPECT_EQ(check_memory_size(max_intx - 1 , 1000 , max_intx - 1 ), Arguments::arg_in_range);
EXPECT_EQ(check_memory_size(max_intx , 1000 , max_intx - 1 ), Arguments::arg_too_big);
EXPECT_EQ(check_memory_size(max_intx - 1 , 1000 , max_intx), Arguments::arg_in_range);
EXPECT_EQ(check_memory_size(max_intx , 1000 , max_intx), Arguments::arg_in_range);
NOT_LP64(
EXPECT_EQ(check_memory_size((julong)max_intx + 1 , 1000 , max_intx), Arguments::arg_too_big);
EXPECT_EQ(check_memory_size( max_intx , 1000 , (julong)max_intx + 1 ), Arguments::arg_in_range);
EXPECT_EQ(check_memory_size((julong)max_intx + 1 , 1000 , (julong)max_intx + 1 ), Arguments::arg_in_range);
EXPECT_EQ(check_memory_size((julong)max_intx + 2 , 1000 , (julong)max_intx + 1 ), Arguments::arg_too_big);
);
}
// A random value - used to verify the output when parsing is expected to fail.
static const intx no_value = 4711 ;
inline intx ArgumentsTest::parse_xss_inner_annotated(const char * str, jint expected_err, const char * file, int line_number) {
intx value = no_value;
jint err = parse_xss(NULL /* Silence error messages */, str, &value);
EXPECT_EQ(err, expected_err) << "Failure from: " << file << ":" << line_number;
return value;
}
// Wrapper around the help function - gives file and line number when a test failure occurs.
#define parse_xss_inner(str, expected_err) ArgumentsTest::parse_xss_inner_annotated(str, expected_err, __FILE__, __LINE__)
static intx calc_expected(julong small_xss_input) {
assert(small_xss_input <= max_julong / 2 , "Sanity" );
// Match code in arguments.cpp
julong julong_ret = align_up(small_xss_input, K) / K;
assert(julong_ret <= (julong)max_intx, "Overflow: " JULONG_FORMAT, julong_ret);
return (intx)julong_ret;
}
static char buff[100 ];
static char * to_string(julong value) {
jio_snprintf(buff, sizeof (buff), JULONG_FORMAT, value);
return buff;
}
TEST_VM_F(ArgumentsTest, parse_xss) {
// Test the maximum input value - should fail.
{
EXPECT_EQ(parse_xss_inner(to_string(max_julong), JNI_EINVAL), no_value);
NOT_LP64(EXPECT_EQ(parse_xss_inner(to_string(max_uintx), JNI_EINVAL), no_value));
}
// Test values "far" away from the uintx boundary,
// but still beyond the max limit.
{
LP64_ONLY(EXPECT_EQ(parse_xss_inner(to_string(max_julong / 2 ), JNI_EINVAL), no_value));
EXPECT_EQ(parse_xss_inner(to_string(INT_MAX), JNI_EINVAL), no_value);
}
// Test at and around the max limit.
{
EXPECT_EQ(parse_xss_inner(to_string(1 * M * K - 1 ), JNI_OK), calc_expected(1 * M * K - 1 ));
EXPECT_EQ(parse_xss_inner(to_string(1 * M * K), JNI_OK), calc_expected(1 * M * K));
EXPECT_EQ(parse_xss_inner(to_string(1 * M * K + 1 ), JNI_EINVAL), no_value);
}
// Test value aligned both to K and vm_page_size.
{
EXPECT_TRUE(is_aligned(32 * M, K));
EXPECT_TRUE(is_aligned(32 * M, (size_t)os::vm_page_size()));
EXPECT_EQ(parse_xss_inner(to_string(32 * M), JNI_OK), (intx)(32 * M / K));
}
// Test around the min limit.
{
EXPECT_EQ(parse_xss_inner(to_string(0 ), JNI_OK), calc_expected(0 ));
EXPECT_EQ(parse_xss_inner(to_string(1 ), JNI_OK), calc_expected(1 ));
EXPECT_EQ(parse_xss_inner(to_string(K - 1 ), JNI_OK), calc_expected(K - 1 ));
EXPECT_EQ(parse_xss_inner(to_string(K), JNI_OK), calc_expected(K));
EXPECT_EQ(parse_xss_inner(to_string(K + 1 ), JNI_OK), calc_expected(K + 1 ));
}
}
struct Dummy {};
static Dummy BAD_INT;
template <typename T>
struct NumericArgument {
bool bad;
const char * str;
T expected_value;
NumericArgument(const char * s, T v) : bad(false ), str(s), expected_value(v) {}
NumericArgument(const char * s, Dummy & dummy) : bad(true ), str(s), expected_value(0 ) {}
};
static void check_invalid_numeric_string(JVMFlag* flag, const char ** invalid_strings) {
for (uint i = 0 ; ; i++) {
const char * str = invalid_strings[i];
if (str == NULL) {
return ;
}
ASSERT_FALSE(ArgumentsTest::parse_argument(flag->name(), str))
<< "Invalid string '" << str
<< "' parsed without error for type " << flag->type_string() << "." ;
}
}
template <typename T>
void check_numeric_flag(JVMFlag* flag, T getvalue(JVMFlag* flag),
NumericArgument<T>* valid_args, size_t n,
bool is_double = false ) {
for (size_t i = 0 ; i < n; i++) {
NumericArgument<T>* info = &valid_args[i];
const char * str = info->str;
if (info->bad) {
ASSERT_FALSE(ArgumentsTest::parse_argument(flag->name(), str))
<< "Invalid string '" << str
<< "' parsed without error for type " << flag->type_string() << "." ;
} else {
ASSERT_TRUE(ArgumentsTest::parse_argument(flag->name(), str))
<< "Valid string '" <<
str << "' did not parse for type " << flag->type_string() << "." ;
ASSERT_EQ(getvalue(flag), info->expected_value)
<< "Valid string '" << str
<< "' did not parse to the correct value for type "
<< flag->type_string() << "." ;
}
}
{
// Invalid strings for *any* numeric type of VM arguments
const char * invalid_strings[] = {
"" , " 1" , "2 " , "3 2" ,
"0x" , "0x0x1" "e"
"K" , "M" , "G" , "1MB" , "1KM" , "AA" , "0B" ,
"18446744073709551615K" , "17179869184G" ,
"0x8000000t" , "0x800000000g" ,
"0x800000000000m" , "0x800000000000000k" ,
"-0x8000000t" , "-0x800000000g" ,
"-0x800000000000m" , "-0x800000000000000k" ,
NULL,
};
check_invalid_numeric_string(flag, invalid_strings);
}
if (is_double) {
const char * invalid_strings_for_double[] = {
"INF" , "Inf" , "Infinity" , "INFINITY" ,
"-INF" , "-Inf" , "-Infinity" , "-INFINITY" ,
"nan" , "NAN" , "NaN" ,
NULL,
};
check_invalid_numeric_string(flag, invalid_strings_for_double);
} else {
const char * invalid_strings_for_integers[] = {
"1.0" , "0x4.5" , "0.001" , "4e10" ,
"999999999999999999999999999999" ,
"0x10000000000000000" , "18446744073709551616" ,
"-0x10000000000000000" , "-18446744073709551616" ,
"-0x8000000000000001" , "-9223372036854775809" ,
NULL,
};
check_invalid_numeric_string(flag, invalid_strings_for_integers);
}
}
#define INTEGER_TEST_TABLE(f) \
/*input i32 u32 i64 u64 */ \
f("0" , 0 , 0 , 0 , 0 ) \
f("-0" , 0 , BAD_INT, 0 , BAD_INT ) \
f("-1" , -1 , BAD_INT, -1 , BAD_INT ) \
f("0x1" , 1 , 1 , 1 , 1 ) \
f("-0x1" , -1 , BAD_INT, -1 , BAD_INT ) \
f("4711" , 4711 , 4711 , 4711 , 4711 ) \
f("1K" , 1024 , 1024 , 1024 , 1024 ) \
f("1k" , 1024 , 1024 , 1024 , 1024 ) \
f("2M" , 2097152 , 2097152 , 2097152 , 2097152 ) \
f("2m" , 2097152 , 2097152 , 2097152 , 2097152 ) \
f("1G" , 1073741824 , 1073741824 , 1073741824 , 1073741824 ) \
f("2G" , BAD_INT, 0 x80000000, 2147483648 LL, 2147483648 ULL ) \
f("1T" , BAD_INT, BAD_INT, 1099511627776 LL, 1099511627776 ULL ) \
f("1t" , BAD_INT, BAD_INT, 1099511627776 LL, 1099511627776 ULL ) \
f("-1K" , -1024 , BAD_INT, -1024 , BAD_INT ) \
f("0x1K" , 1024 , 1024 , 1024 , 1024 ) \
f("-0x1K" , -1024 , BAD_INT, -1024 , BAD_INT ) \
f("0K" , 0 , 0 , 0 , 0 ) \
f("0x1000000k" , BAD_INT, BAD_INT, 17179869184 LL, 17179869184 ULL ) \
f("0x800000m" , BAD_INT, BAD_INT, 0 x80000000000LL, 0 x80000000000ULL ) \
f("0x8000g" , BAD_INT, BAD_INT, 0 x200000000000LL, 0 x200000000000ULL ) \
f("0x8000t" , BAD_INT, BAD_INT, 0 x80000000000000LL, 0 x80000000000000ULL ) \
f("-0x1000000k" , BAD_INT, BAD_INT, -17179869184 LL, BAD_INT ) \
f("-0x800000m" , BAD_INT, BAD_INT, -0 x80000000000LL, BAD_INT ) \
f("-0x8000g" , BAD_INT, BAD_INT, -0 x200000000000LL, BAD_INT ) \
f("-0x8000t" , BAD_INT, BAD_INT, -0 x80000000000000LL, BAD_INT ) \
f("0x7fffffff" , 0 x7fffffff, 0 x7fffffff, 0 x7fffffff, 0 x7fffffff ) \
f("0xffffffff" , BAD_INT, 0 xffffffff, 0 xffffffff, 0 xffffffff ) \
f("0x80000000" , BAD_INT, 0 x80000000, 0 x80000000, 0 x80000000 ) \
f("-0x7fffffff" , -2147483647 , BAD_INT, -2147483647 LL, BAD_INT ) \
f("-0x80000000" , -2147483648 , BAD_INT, -2147483648 LL, BAD_INT ) \
f("-0x80000001" , BAD_INT, BAD_INT, -2147483649 LL, BAD_INT ) \
f("0x100000000" , BAD_INT, BAD_INT, 0 x100000000LL, 0 x100000000ULL ) \
f("0xcafebabe" , BAD_INT, 0 xcafebabe, 0 xcafebabe, 0 xcafebabe ) \
f("0XCAFEBABE" , BAD_INT, 0 xcafebabe, 0 xcafebabe, 0 xcafebabe ) \
f("0XCAFEbabe" , BAD_INT, 0 xcafebabe, 0 xcafebabe, 0 xcafebabe ) \
f("0xcafebabe1" , BAD_INT, BAD_INT, 0 xcafebabe1, 0 xcafebabe1 ) \
f("0x7fffffffffffffff" , BAD_INT, BAD_INT, max_jlong, 9223372036854775807 ULL ) \
f("0x8000000000000000" , BAD_INT, BAD_INT, BAD_INT, 9223372036854775808 ULL ) \
f("0xffffffffffffffff" , BAD_INT, BAD_INT, BAD_INT, max_julong ) \
f("9223372036854775807" , BAD_INT, BAD_INT, 9223372036854775807 LL, 9223372036854775807 ULL ) \
f("9223372036854775808" , BAD_INT, BAD_INT, BAD_INT, 9223372036854775808 ULL ) \
f("-9223372036854775808" , BAD_INT, BAD_INT, min_jlong, BAD_INT ) \
f("18446744073709551615" , BAD_INT, BAD_INT, BAD_INT, max_julong ) \
\
/* All edge cases without a k/m/g/t suffix */ \
f("0x7ffffffe" , max_jint-1 , 0 x7ffffffe, 0 x7ffffffeLL, 0 x7ffffffeULL ) \
f("0x7fffffff" , max_jint, 0 x7fffffff, 0 x7fffffffLL, 0 x7fffffffULL ) \
f("0x80000000" , BAD_INT, 0 x80000000, 0 x80000000LL, 0 x80000000ULL ) \
f("0xfffffffe" , BAD_INT, max_juint-1 , 0 xfffffffeLL, 0 xfffffffeULL ) \
f("0xffffffff" , BAD_INT, max_juint, 0 xffffffffLL, 0 xffffffffULL ) \
f("0x100000000" , BAD_INT, BAD_INT, 0 x100000000LL, 0 x100000000ULL ) \
f("-0x7fffffff" , min_jint+1 , BAD_INT, -0 x7fffffffLL, BAD_INT ) \
f("-0x80000000" , min_jint, BAD_INT, -0 x80000000LL, BAD_INT ) \
f("-0x80000001" , BAD_INT, BAD_INT, -0 x80000001LL, BAD_INT ) \
\
f("0x7ffffffffffffffe" , BAD_INT, BAD_INT, max_jlong-1 , 0 x7ffffffffffffffeULL ) \
f("0x7fffffffffffffff" , BAD_INT, BAD_INT, max_jlong, 0 x7fffffffffffffffULL ) \
f("0x8000000000000000" , BAD_INT, BAD_INT, BAD_INT, 0 x8000000000000000ULL ) \
f("0xfffffffffffffffe" , BAD_INT, BAD_INT, BAD_INT, max_julong-1 ) \
f("0xffffffffffffffff" , BAD_INT, BAD_INT, BAD_INT, max_julong ) \
f("0x10000000000000000" , BAD_INT, BAD_INT, BAD_INT, BAD_INT ) \
f("-0x7fffffffffffffff" , BAD_INT, BAD_INT, min_jlong+1 , BAD_INT ) \
f("-0x8000000000000000" , BAD_INT, BAD_INT, min_jlong, BAD_INT ) \
f("-0x8000000000000001" , BAD_INT, BAD_INT, BAD_INT, BAD_INT ) \
\
/* edge cases for suffix: K */ \
f("0x1ffffek" , 0 x1ffffe * k, 0 x1ffffeU * k,0 x1ffffeLL * k, 0 x1ffffeULL * k ) \
f("0x1fffffk" , 0 x1fffff * k, 0 x1fffffU * k,0 x1fffffLL * k, 0 x1fffffULL * k ) \
f("0x200000k" , BAD_INT, 0 x200000U * k,0 x200000LL * k, 0 x200000ULL * k ) \
f("0x3ffffek" , BAD_INT, 0 x3ffffeU * k,0 x3ffffeLL * k, 0 x3ffffeULL * k ) \
f("0x3fffffk" , BAD_INT, 0 x3fffffU * k,0 x3fffffLL * k, 0 x3fffffULL * k ) \
f("0x400000k" , BAD_INT, BAD_INT, 0 x400000LL * k, 0 x400000ULL * k ) \
f("-0x1fffffk" , -0 x1fffff * k, BAD_INT, -0 x1fffffLL * k, BAD_INT ) \
f("-0x200000k" , -0 x200000 * k, BAD_INT, -0 x200000LL * k, BAD_INT ) \
f("-0x200001k" , BAD_INT, BAD_INT, -0 x200001LL * k, BAD_INT ) \
\
f("0x1ffffffffffffek" , BAD_INT, BAD_INT, 0 x1ffffffffffffeLL * k, 0 x1ffffffffffffeULL * k ) \
f("0x1fffffffffffffk" , BAD_INT, BAD_INT, 0 x1fffffffffffffLL * k, 0 x1fffffffffffffULL * k ) \
f("0x20000000000000k" , BAD_INT, BAD_INT, BAD_INT, 0 x20000000000000ULL * k ) \
f("0x3ffffffffffffek" , BAD_INT, BAD_INT, BAD_INT, 0 x3ffffffffffffeULL * k ) \
f("0x3fffffffffffffk" , BAD_INT, BAD_INT, BAD_INT, 0 x3fffffffffffffULL * k ) \
f("0x40000000000000k" , BAD_INT, BAD_INT, BAD_INT, BAD_INT ) \
f("-0x1fffffffffffffk" , BAD_INT, BAD_INT, -0 x1fffffffffffffLL * k, BAD_INT ) \
f("-0x20000000000000k" , BAD_INT, BAD_INT, -0 x20000000000000LL * k, BAD_INT ) \
f("-0x20000000000001k" , BAD_INT, BAD_INT, BAD_INT, BAD_INT ) \
\
/* edge cases for suffix: M */ \
f("0x7fem" , 0 x7fe * m, 0 x7feU * m, 0 x7feLL * m, 0 x7feULL * m ) \
f("0x7ffm" , 0 x7ff * m, 0 x7ffU * m, 0 x7ffLL * m, 0 x7ffULL * m ) \
f("0x800m" , BAD_INT, 0 x800U * m, 0 x800LL * m, 0 x800ULL * m ) \
f("0xffem" , BAD_INT, 0 xffeU * m, 0 xffeLL * m, 0 xffeULL * m ) \
f("0xfffm" , BAD_INT, 0 xfffU * m, 0 xfffLL * m, 0 xfffULL * m ) \
f("0x1000m" , BAD_INT, BAD_INT, 0 x1000LL * m, 0 x1000ULL * m ) \
f("-0x7ffm" , -0 x7ff * m, BAD_INT, -0 x7ffLL * m, BAD_INT ) \
f("-0x800m" , -0 x800 * m, BAD_INT, -0 x800LL * m, BAD_INT ) \
f("-0x801m" , BAD_INT, BAD_INT, -0 x801LL * m, BAD_INT ) \
\
f("0x7fffffffffem" , BAD_INT, BAD_INT, 0 x7fffffffffeLL * m, 0 x7fffffffffeULL * m ) \
f("0x7ffffffffffm" , BAD_INT, BAD_INT, 0 x7ffffffffffLL * m, 0 x7ffffffffffULL * m ) \
f("0x80000000000m" , BAD_INT, BAD_INT, BAD_INT, 0 x80000000000ULL * m ) \
f("0xffffffffffem" , BAD_INT, BAD_INT, BAD_INT, 0 xffffffffffeULL * m ) \
f("0xfffffffffffm" , BAD_INT, BAD_INT, BAD_INT, 0 xfffffffffffULL * m ) \
f("0x100000000000m" , BAD_INT, BAD_INT, BAD_INT, BAD_INT ) \
f("-0x7ffffffffffm" , BAD_INT, BAD_INT, -0 x7ffffffffffLL * m, BAD_INT ) \
f("-0x80000000000m" , BAD_INT, BAD_INT, -0 x80000000000LL * m, BAD_INT ) \
f("-0x80000000001m" , BAD_INT, BAD_INT, BAD_INT, BAD_INT ) \
\
/* edge cases for suffix: G */ \
f("0x0g" , 0 x0 * g, 0 x0U * g, 0 x0LL * g, 0 x0ULL * g ) \
f("0x1g" , 0 x1 * g, 0 x1U * g, 0 x1LL * g, 0 x1ULL * g ) \
f("0x2g" , BAD_INT, 0 x2U * g, 0 x2LL * g, 0 x2ULL * g ) \
f("0x3g" , BAD_INT, 0 x3U * g, 0 x3LL * g, 0 x3ULL * g ) \
f("0x4g" , BAD_INT, BAD_INT, 0 x4LL * g, 0 x4ULL * g ) \
f("-0x1g" , -0 x1 * g, BAD_INT, -0 x1LL * g, BAD_INT ) \
f("-0x2g" , -0 x2 * g, BAD_INT, -0 x2LL * g, BAD_INT ) \
f("-0x3g" , BAD_INT, BAD_INT, -0 x3LL * g, BAD_INT ) \
\
f("0x1fffffffeg" , BAD_INT, BAD_INT, 0 x1fffffffeLL * g, 0 x1fffffffeULL * g ) \
f("0x1ffffffffg" , BAD_INT, BAD_INT, 0 x1ffffffffLL * g, 0 x1ffffffffULL * g ) \
f("0x200000000g" , BAD_INT, BAD_INT, BAD_INT, 0 x200000000ULL * g ) \
f("0x3fffffffeg" , BAD_INT, BAD_INT, BAD_INT, 0 x3fffffffeULL * g ) \
f("0x3ffffffffg" , BAD_INT, BAD_INT, BAD_INT, 0 x3ffffffffULL * g ) \
f("0x400000000g" , BAD_INT, BAD_INT, BAD_INT, BAD_INT ) \
f("-0x1ffffffffg" , BAD_INT, BAD_INT, -0 x1ffffffffLL * g, BAD_INT ) \
f("-0x200000000g" , BAD_INT, BAD_INT, -0 x200000000LL * g, BAD_INT ) \
f("-0x200000001g" , BAD_INT, BAD_INT, BAD_INT, BAD_INT ) \
\
/* edge cases for suffix: T */ \
f("0x7ffffet" , BAD_INT, BAD_INT, 0 x7ffffeLL * t, 0 x7ffffeULL * t ) \
f("0x7ffffft" , BAD_INT, BAD_INT, 0 x7fffffLL * t, 0 x7fffffULL * t ) \
f("0x800000t" , BAD_INT, BAD_INT, BAD_INT, 0 x800000ULL * t ) \
f("0xfffffet" , BAD_INT, BAD_INT, BAD_INT, 0 xfffffeULL * t ) \
f("0xfffffft" , BAD_INT, BAD_INT, BAD_INT, 0 xffffffULL * t ) \
f("0x1000000t" , BAD_INT, BAD_INT, BAD_INT, BAD_INT ) \
f("-0x7ffffft" , BAD_INT, BAD_INT, -0 x7fffffLL * t, BAD_INT ) \
f("-0x800000t" , BAD_INT, BAD_INT, -0 x800000LL * t, BAD_INT ) \
f("-0x800001t" , BAD_INT, BAD_INT, BAD_INT, BAD_INT )
#define INTEGER_TEST_i32(s, i32, u32, i64, u64) NumericArgument<T>(s, i32),
#define INTEGER_TEST_u32(s, i32, u32, i64, u64) NumericArgument<T>(s, u32),
#define INTEGER_TEST_i64(s, i32, u32, i64, u64) NumericArgument<T>(s, i64),
#define INTEGER_TEST_u64(s, i32, u32, i64, u64) NumericArgument<T>(s, u64),
// signed 32-bit
template <typename T, ENABLE_IF(std::is_signed<T>::value), ENABLE_IF(sizeof (T) == 4 )>
void check_flag(const char * f, T getvalue(JVMFlag* flag)) {
JVMFlag* flag = JVMFlag::find_flag(f);
if (flag == NULL) { // not available in product builds
return ;
}
T k = static_cast <T>(K);
T m = static_cast <T>(M);
T g = static_cast <T>(G);
NumericArgument<T> valid_strings[] = { INTEGER_TEST_TABLE(INTEGER_TEST_i32) };
check_numeric_flag(flag, getvalue, valid_strings, ARRAY_SIZE(valid_strings));
}
// unsigned 32-bit
template <typename T, ENABLE_IF(!std::is_signed<T>::value), ENABLE_IF(sizeof (T) == 4 )>
void check_flag(const char * f, T getvalue(JVMFlag* flag)) {
JVMFlag* flag = JVMFlag::find_flag(f);
if (flag == NULL) { // not available in product builds
return ;
}
T k = static_cast <T>(K);
T m = static_cast <T>(M);
T g = static_cast <T>(G);
NumericArgument<T> valid_strings[] = { INTEGER_TEST_TABLE(INTEGER_TEST_u32) };
check_numeric_flag(flag, getvalue, valid_strings, ARRAY_SIZE(valid_strings));
}
// signed 64-bit
template <typename T, ENABLE_IF(std::is_signed<T>::value), ENABLE_IF(sizeof (T) == 8 )>
void check_flag(const char * f, T getvalue(JVMFlag* flag)) {
JVMFlag* flag = JVMFlag::find_flag(f);
if (flag == NULL) { // not available in product builds
return ;
}
T k = static_cast <T>(K);
T m = static_cast <T>(M);
T g = static_cast <T>(G);
T t = static_cast <T>(G) * k;
NumericArgument<T> valid_strings[] = { INTEGER_TEST_TABLE(INTEGER_TEST_i64) };
check_numeric_flag(flag, getvalue, valid_strings, ARRAY_SIZE(valid_strings));
}
// unsigned 64-bit
template <typename T, ENABLE_IF(!std::is_signed<T>::value), ENABLE_IF(sizeof (T) == 8 )>
void check_flag(const char * f, T getvalue(JVMFlag* flag)) {
JVMFlag* flag = JVMFlag::find_flag(f);
if (flag == NULL) { // not available in product builds
return ;
}
T k = static_cast <T>(K);
T m = static_cast <T>(M);
T g = static_cast <T>(G);
T t = static_cast <T>(G) * k;
NumericArgument<T> valid_strings[] = { INTEGER_TEST_TABLE(INTEGER_TEST_u64) };
check_numeric_flag(flag, getvalue, valid_strings, ARRAY_SIZE(valid_strings));
}
// Testing the parsing of -XX:<SomeFlag>=<an integer value>
//
// All of the integral types that can be used for command line options:
// int, uint, intx, uintx, uint64_t, size_t
//
// In all supported platforms, these types can be mapped to only 4 native types:
// {signed, unsigned} x {32-bit, 64-bit}
//
// We use SFINAE to pick the correct column in the INTEGER_TEST_TABLE for each type.
TEST_VM_F(ArgumentsTest, set_numeric_flag_int) {
check_flag<int >("TestFlagFor_int" , [] (JVMFlag* flag) {
return flag->get_int();
});
}
TEST_VM_F(ArgumentsTest, set_numeric_flag_uint) {
check_flag<uint>("TestFlagFor_uint" , [] (JVMFlag* flag) {
return flag->get_uint();
});
}
TEST_VM_F(ArgumentsTest, set_numeric_flag_intx) {
check_flag<intx>("TestFlagFor_intx" , [] (JVMFlag* flag) {
return flag->get_intx();
});
}
TEST_VM_F(ArgumentsTest, set_numeric_flag_uintx) {
check_flag<uintx>("TestFlagFor_uintx" , [] (JVMFlag* flag) {
return flag->get_uintx();
});
}
TEST_VM_F(ArgumentsTest, set_numeric_flag_uint64_t) {
check_flag<uint64_t>("TestFlagFor_uint64_t" , [] (JVMFlag* flag) {
return flag->get_uint64_t();
});
}
TEST_VM_F(ArgumentsTest, set_numeric_flag_size_t) {
check_flag<size_t>("TestFlagFor_size_t" , [] (JVMFlag* flag) {
return flag->get_size_t();
});
}
TEST_VM_F(ArgumentsTest, set_numeric_flag_double) {
JVMFlag* flag = JVMFlag::find_flag("TestFlagFor_double" );
if (flag == NULL) { // not available in product builds
return ;
}
NumericArgument<double > valid_strings[] = {
NumericArgument<double >("0" , 0 .0 ),
NumericArgument<double >("1" , 1 .0 ),
NumericArgument<double >("-0" , -0 .0 ),
NumericArgument<double >("-1" , -1 .0 ),
};
auto getvalue = [] (JVMFlag* flag) {
return flag->get_double();
};
check_numeric_flag<double >(flag, getvalue, valid_strings,
ARRAY_SIZE(valid_strings), /*is_double=*/true);
const char * more_test_strings[] = {
// These examples are from https://en.cppreference.com/w/cpp/language/floating_literal
// (but with the L and F suffix removed).
"1e10" , "1e-5" ,
"1.e-2" , "3.14" ,
".1" , "0.1e-1" ,
"0x1ffp10" , "0X0p-1" ,
"0x1.p0" , "0xf.p-1" ,
"0x0.123p-1" , "0xa.bp10" ,
"0x1.4p3" ,
// More test cases
"1.5" , "6.02e23" , "-6.02e+23" ,
"1.7976931348623157E+308" , // max double
"-0" , "0" ,
"0x1.91eb85p+1" ,
"999999999999999999999999999999" ,
};
for (uint i = 0 ; i < ARRAY_SIZE(more_test_strings); i++) {
const char * str = more_test_strings[i];
char * end;
errno = 0 ;
double expected = strtod(str, &end);
if (errno == 0 && end != NULL && *end == '\0' ) {
ASSERT_TRUE(ArgumentsTest::parse_argument(flag->name(), str))
<< "Test string '" <<
str << "' did not parse for type " << flag->type_string() << ". (Expected value = " << expected << ")" ;
double d = flag->get_double();
ASSERT_TRUE(d == expected)
<< "Parsed number " << d << " is not the same as expected " << expected;
} else {
// Some of the strings like "1.e-2" are not valid in certain locales.
// The decimal-point character is also locale dependent.
ASSERT_FALSE(ArgumentsTest::parse_argument(flag->name(), str))
<< "Invalid string '" << str << "' parsed without error." ;
}
}
}
Messung V0.5 in Prozent C=95 H=95 G=94
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.27Bemerkung:
¤
*Bot Zugriff