151c0b2f7Stbbdev /*
2b15aabb3Stbbdev Copyright (c) 2005-2021 Intel Corporation
351c0b2f7Stbbdev
451c0b2f7Stbbdev Licensed under the Apache License, Version 2.0 (the "License");
551c0b2f7Stbbdev you may not use this file except in compliance with the License.
651c0b2f7Stbbdev You may obtain a copy of the License at
751c0b2f7Stbbdev
851c0b2f7Stbbdev http://www.apache.org/licenses/LICENSE-2.0
951c0b2f7Stbbdev
1051c0b2f7Stbbdev Unless required by applicable law or agreed to in writing, software
1151c0b2f7Stbbdev distributed under the License is distributed on an "AS IS" BASIS,
1251c0b2f7Stbbdev WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1351c0b2f7Stbbdev See the License for the specific language governing permissions and
1451c0b2f7Stbbdev limitations under the License.
1551c0b2f7Stbbdev */
1651c0b2f7Stbbdev
1751c0b2f7Stbbdev //! \file test_environment_whitebox.cpp
1851c0b2f7Stbbdev //! \brief Test for [internal] functionality
1951c0b2f7Stbbdev
20*478de5b1Stbbdev #if _WIN32 || _WIN64
21*478de5b1Stbbdev #define _CRT_SECURE_NO_WARNINGS
22*478de5b1Stbbdev #endif
23*478de5b1Stbbdev
2451c0b2f7Stbbdev #include "common/test.h"
2551c0b2f7Stbbdev #include "common/utils.h"
2651c0b2f7Stbbdev #include "common/utils_env.h"
27*478de5b1Stbbdev #include "src/tbb/environment.h"
2851c0b2f7Stbbdev
2951c0b2f7Stbbdev #include <string>
3051c0b2f7Stbbdev #include <algorithm>
3151c0b2f7Stbbdev #include <sstream>
3251c0b2f7Stbbdev #include <climits>
3351c0b2f7Stbbdev #include <utility>
3451c0b2f7Stbbdev #include <vector>
3551c0b2f7Stbbdev
3651c0b2f7Stbbdev const char* environment_variable_name = "TEST_VARIABLE_NAME";
3751c0b2f7Stbbdev
3851c0b2f7Stbbdev // For WIN8UI applications reading and writing the environment variables
3951c0b2f7Stbbdev // is prohibited due to the platform limitations
4051c0b2f7Stbbdev #if !__TBB_WIN8UI_SUPPORT
4151c0b2f7Stbbdev
4251c0b2f7Stbbdev #if _WIN32 || _WIN64
4351c0b2f7Stbbdev // Environment variable length is limited by 32K on Windows
4451c0b2f7Stbbdev const std::size_t large_length = 32000;
4551c0b2f7Stbbdev #else
4651c0b2f7Stbbdev const std::size_t large_length = 1000000;
4751c0b2f7Stbbdev #endif
4851c0b2f7Stbbdev
4951c0b2f7Stbbdev template <typename T>
set_and_get_test_variable(T (* environment_variable_getter)(const char *),std::pair<std::string,T> test_case)5051c0b2f7Stbbdev void set_and_get_test_variable( T (*environment_variable_getter)( const char* ),
5151c0b2f7Stbbdev std::pair<std::string, T> test_case )
5251c0b2f7Stbbdev {
5351c0b2f7Stbbdev utils::SetEnv(environment_variable_name, test_case.first.c_str());
5451c0b2f7Stbbdev T result = environment_variable_getter(environment_variable_name);
5551c0b2f7Stbbdev REQUIRE_MESSAGE(result == test_case.second, "Wrong Get<Type>EnvironmentVariable return value");
5651c0b2f7Stbbdev utils::SetEnv(environment_variable_name, "");
5751c0b2f7Stbbdev }
5851c0b2f7Stbbdev
5951c0b2f7Stbbdev utils::FastRandom<> rnd(12345);
6051c0b2f7Stbbdev
6151c0b2f7Stbbdev struct RandomCharacterGenerator {
operator ()RandomCharacterGenerator6251c0b2f7Stbbdev char operator()() {
6351c0b2f7Stbbdev return rnd.get() % 128; // 127 - the last ASCII symbol
6451c0b2f7Stbbdev }
6551c0b2f7Stbbdev }; // struct RandomCharacterGenerator
6651c0b2f7Stbbdev
alternative_env_variable_checker(const char * str,bool)6751c0b2f7Stbbdev bool alternative_env_variable_checker( const char* str, bool ) {
6851c0b2f7Stbbdev bool result = false;
6951c0b2f7Stbbdev for (unsigned i = 0; str[i]; ++i) {
7051c0b2f7Stbbdev if (str[i] == '1') {
7151c0b2f7Stbbdev // if we found more then one '1' character -> return false
7251c0b2f7Stbbdev result = !result;
7351c0b2f7Stbbdev if (!result) return false;
7451c0b2f7Stbbdev } else if (str[i] != ' ') {
7551c0b2f7Stbbdev // if we found some character other than ' ' and '1' -> return false
7651c0b2f7Stbbdev return false;
7751c0b2f7Stbbdev }
7851c0b2f7Stbbdev }
7951c0b2f7Stbbdev return result;
8051c0b2f7Stbbdev }
8151c0b2f7Stbbdev
8251c0b2f7Stbbdev // Suitable alternative checker for GetLongEnvVariable() was not found
8351c0b2f7Stbbdev // So here we use the code from GetLongEnvVariable() realization
alternative_env_variable_checker(const char * str,long)8451c0b2f7Stbbdev long alternative_env_variable_checker( const char* str, long ) {
8551c0b2f7Stbbdev char* end;
8651c0b2f7Stbbdev errno = 0;
8751c0b2f7Stbbdev long result = std::strtol(str, &end, 10);
8851c0b2f7Stbbdev
8951c0b2f7Stbbdev // We have exceeded the range, value is negative or it is the end of the string
9051c0b2f7Stbbdev if (errno == ERANGE || result < 0 || end == str) {
9151c0b2f7Stbbdev result = -1;
9251c0b2f7Stbbdev }
9351c0b2f7Stbbdev
9451c0b2f7Stbbdev for (; *end != '\0'; ++end) {
9551c0b2f7Stbbdev if (!std::isspace(*end))
9651c0b2f7Stbbdev result = -1;
9751c0b2f7Stbbdev }
9851c0b2f7Stbbdev return result;
9951c0b2f7Stbbdev }
10051c0b2f7Stbbdev
10151c0b2f7Stbbdev template <typename T>
create_random_case(std::size_t length)10251c0b2f7Stbbdev std::pair<std::string, T> create_random_case( std::size_t length ) {
10351c0b2f7Stbbdev REQUIRE_MESSAGE(length != 0, "Requested random string cannot be empty");
10451c0b2f7Stbbdev std::string rand_string(length, ' ');
10551c0b2f7Stbbdev std::generate(rand_string.begin(), rand_string.end(), RandomCharacterGenerator{});
10651c0b2f7Stbbdev
10751c0b2f7Stbbdev T expected_result = alternative_env_variable_checker(rand_string.c_str(), T());
10851c0b2f7Stbbdev
10951c0b2f7Stbbdev return std::make_pair(rand_string, expected_result);
11051c0b2f7Stbbdev }
11151c0b2f7Stbbdev
11251c0b2f7Stbbdev template <typename T>
prepare_random_cases(std::vector<std::pair<std::string,T>> & cases)11351c0b2f7Stbbdev void prepare_random_cases( std::vector<std::pair<std::string, T>>& cases ) {
11451c0b2f7Stbbdev // Random cases
11551c0b2f7Stbbdev std::size_t length = 10000;
11651c0b2f7Stbbdev
11751c0b2f7Stbbdev for (std::size_t i = 0; i < 10; ++i) {
11851c0b2f7Stbbdev cases.push_back(create_random_case<T>((rnd.get() % length) + 1));
11951c0b2f7Stbbdev }
12051c0b2f7Stbbdev
12151c0b2f7Stbbdev // Random case with large string
12251c0b2f7Stbbdev cases.push_back(create_random_case<T>(large_length));
12351c0b2f7Stbbdev }
12451c0b2f7Stbbdev
initialize_cases(bool wrong_result)12551c0b2f7Stbbdev std::vector<std::pair<std::string, bool>> initialize_cases( bool wrong_result ) {
12651c0b2f7Stbbdev std::vector<std::pair<std::string, bool>> cases;
12751c0b2f7Stbbdev // Valid cases
12851c0b2f7Stbbdev cases.push_back(std::make_pair("1", true));
12951c0b2f7Stbbdev cases.push_back(std::make_pair(" 1 ", true));
13051c0b2f7Stbbdev cases.push_back(std::make_pair("1 ", true));
13151c0b2f7Stbbdev cases.push_back(std::make_pair(" 1 ", true));
13251c0b2f7Stbbdev cases.push_back(std::make_pair(" 1", true));
13351c0b2f7Stbbdev cases.push_back(std::make_pair((std::string(large_length, ' ') + '1').c_str(), true));
13451c0b2f7Stbbdev
13551c0b2f7Stbbdev // Invalid cases
13651c0b2f7Stbbdev cases.push_back(std::make_pair("", wrong_result));
13751c0b2f7Stbbdev cases.push_back(std::make_pair(" ", wrong_result));
13851c0b2f7Stbbdev cases.push_back(std::make_pair(" 11", wrong_result));
13951c0b2f7Stbbdev cases.push_back(std::make_pair("111111", wrong_result));
14051c0b2f7Stbbdev cases.push_back(std::make_pair("1 1", wrong_result));
14151c0b2f7Stbbdev cases.push_back(std::make_pair(" 1 abc?", wrong_result));
14251c0b2f7Stbbdev cases.push_back(std::make_pair("1;", wrong_result));
14351c0b2f7Stbbdev cases.push_back(std::make_pair(" d ", wrong_result));
14451c0b2f7Stbbdev cases.push_back(std::make_pair("0", wrong_result));
14551c0b2f7Stbbdev cases.push_back(std::make_pair("0 ", wrong_result));
14651c0b2f7Stbbdev cases.push_back(std::make_pair("000000", wrong_result));
14751c0b2f7Stbbdev cases.push_back(std::make_pair("01", wrong_result));
14851c0b2f7Stbbdev cases.push_back(std::make_pair("00000001", wrong_result));
14951c0b2f7Stbbdev cases.push_back(std::make_pair("ABCDEFG", wrong_result));
15051c0b2f7Stbbdev cases.push_back(std::make_pair("2018", wrong_result));
15151c0b2f7Stbbdev cases.push_back(std::make_pair("ABC_123", wrong_result));
15251c0b2f7Stbbdev cases.push_back(std::make_pair("true", wrong_result));
15351c0b2f7Stbbdev cases.push_back(std::make_pair(std::string(large_length, 'A').c_str(), wrong_result));
15451c0b2f7Stbbdev
15551c0b2f7Stbbdev prepare_random_cases(cases);
15651c0b2f7Stbbdev return cases;
15751c0b2f7Stbbdev }
15851c0b2f7Stbbdev
initialize_cases(long wrong_result)15951c0b2f7Stbbdev std::vector<std::pair<std::string, long>> initialize_cases( long wrong_result ) {
16051c0b2f7Stbbdev std::vector<std::pair<std::string, long>> cases;
16151c0b2f7Stbbdev std::stringstream ss;
16251c0b2f7Stbbdev // Valid cases
16351c0b2f7Stbbdev for (long i = 0; i < 100; ++i) {
16451c0b2f7Stbbdev ss << i;
16551c0b2f7Stbbdev cases.push_back(std::make_pair(ss.str().c_str(), i));
16651c0b2f7Stbbdev ss.str("");
16751c0b2f7Stbbdev
16851c0b2f7Stbbdev ss << " " << i << " ";
16951c0b2f7Stbbdev cases.push_back(std::make_pair(ss.str().c_str(), i));
17051c0b2f7Stbbdev ss.str("");
17151c0b2f7Stbbdev
17251c0b2f7Stbbdev ss << i << " ";
17351c0b2f7Stbbdev cases.push_back(std::make_pair(ss.str().c_str(), i));
17451c0b2f7Stbbdev ss.str("");
17551c0b2f7Stbbdev
17651c0b2f7Stbbdev ss << " " << i;
17751c0b2f7Stbbdev cases.push_back(std::make_pair(ss.str().c_str(), i));
17851c0b2f7Stbbdev ss.str("");
17951c0b2f7Stbbdev }
18051c0b2f7Stbbdev
18151c0b2f7Stbbdev ss << LONG_MAX;
18251c0b2f7Stbbdev cases.push_back(std::make_pair(ss.str().c_str(), LONG_MAX));
18351c0b2f7Stbbdev ss.str("");
18451c0b2f7Stbbdev
18551c0b2f7Stbbdev cases.push_back(std::make_pair((std::string(large_length, ' ') + '1').c_str(), 1L));
18651c0b2f7Stbbdev
18751c0b2f7Stbbdev // Invalid cases
18851c0b2f7Stbbdev cases.push_back(std::make_pair("", wrong_result));
18951c0b2f7Stbbdev cases.push_back(std::make_pair(" ", wrong_result));
19051c0b2f7Stbbdev cases.push_back(std::make_pair("a", wrong_result));
19151c0b2f7Stbbdev cases.push_back(std::make_pair("^&*", wrong_result));
19251c0b2f7Stbbdev cases.push_back(std::make_pair(" 10 e", wrong_result));
19351c0b2f7Stbbdev cases.push_back(std::make_pair("a 12", wrong_result));
19451c0b2f7Stbbdev cases.push_back(std::make_pair("eeeeeeeeeeeeeeeeee", wrong_result));
19551c0b2f7Stbbdev cases.push_back(std::make_pair("200000000000000000000000000", wrong_result));
19651c0b2f7Stbbdev cases.push_back(std::make_pair("-1", wrong_result));
19751c0b2f7Stbbdev cases.push_back(std::make_pair("-100", wrong_result));
19851c0b2f7Stbbdev cases.push_back(std::make_pair("-200000000000000000000000000", wrong_result));
19951c0b2f7Stbbdev cases.push_back(std::make_pair("ABBDDRR", wrong_result));
20051c0b2f7Stbbdev cases.push_back(std::make_pair("10 10", wrong_result));
20151c0b2f7Stbbdev cases.push_back(std::make_pair("true", wrong_result));
20251c0b2f7Stbbdev cases.push_back(std::make_pair("false", wrong_result));
20351c0b2f7Stbbdev cases.push_back(std::make_pair("1A", wrong_result));
20451c0b2f7Stbbdev cases.push_back(std::make_pair("_123", wrong_result));
20551c0b2f7Stbbdev cases.push_back(std::make_pair(std::string(large_length, 'A').c_str(), wrong_result));
20651c0b2f7Stbbdev
20751c0b2f7Stbbdev // Prepare string with LONG_MAX + 1 value
20851c0b2f7Stbbdev ss << LONG_MAX / 10 << (LONG_MAX % 10 + 1);
20951c0b2f7Stbbdev cases.push_back(std::make_pair(ss.str().c_str(), -1));
21051c0b2f7Stbbdev ss.str("");
21151c0b2f7Stbbdev
21251c0b2f7Stbbdev prepare_random_cases(cases);
21351c0b2f7Stbbdev return cases;
21451c0b2f7Stbbdev }
21551c0b2f7Stbbdev
21651c0b2f7Stbbdev template <typename T>
test_environment_variable(T (* environment_variables_handler)(const char *),T wrong_result)21751c0b2f7Stbbdev void test_environment_variable( T (*environment_variables_handler)( const char* ), T wrong_result ) {
21851c0b2f7Stbbdev REQUIRE_MESSAGE(environment_variables_handler(environment_variable_name) == wrong_result,
21951c0b2f7Stbbdev "Tested environment variable should not be defined in the beginning");
22051c0b2f7Stbbdev
22151c0b2f7Stbbdev // Each pair is a test case:
22251c0b2f7Stbbdev // pair.first -> value of environment variable
22351c0b2f7Stbbdev // pair.second -> expected result
22451c0b2f7Stbbdev std::vector<std::pair<std::string, T>> cases = initialize_cases(wrong_result);
22551c0b2f7Stbbdev
22651c0b2f7Stbbdev for (std::size_t i = 0; i != cases.size(); ++i) {
22751c0b2f7Stbbdev set_and_get_test_variable(environment_variables_handler, cases[i]);
22851c0b2f7Stbbdev }
22951c0b2f7Stbbdev }
23051c0b2f7Stbbdev
23151c0b2f7Stbbdev //! \brief \ref error_guessing
23251c0b2f7Stbbdev TEST_CASE("testing GetBoolEnvironmentVariable") {
23351c0b2f7Stbbdev test_environment_variable(tbb::detail::r1::GetBoolEnvironmentVariable, false);
23451c0b2f7Stbbdev }
23551c0b2f7Stbbdev
23651c0b2f7Stbbdev //! \brief \ref error_guessing
23751c0b2f7Stbbdev TEST_CASE("testing GetIntegralEnvironmentVariable") {
23851c0b2f7Stbbdev test_environment_variable(tbb::detail::r1::GetIntegralEnvironmentVariable, -1L);
23951c0b2f7Stbbdev }
24051c0b2f7Stbbdev
24151c0b2f7Stbbdev #endif // !__TBB_WIN8UI_SUPPORT
242