diff --git a/Microsoft.WindowsAzure.Storage/tests/blob_streams_test.cpp b/Microsoft.WindowsAzure.Storage/tests/blob_streams_test.cpp index 7bc28de9..c92a931e 100644 --- a/Microsoft.WindowsAzure.Storage/tests/blob_streams_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/blob_streams_test.cpp @@ -620,7 +620,7 @@ SUITE(Blob) TEST_FIXTURE(block_blob_test_base, block_blob_write_stream_maximum_execution_time) { - std::chrono::milliseconds duration(300); + std::chrono::seconds duration(10); azure::storage::blob_request_options options; options.set_maximum_execution_time(duration); diff --git a/Microsoft.WindowsAzure.Storage/tests/blob_test_base.cpp b/Microsoft.WindowsAzure.Storage/tests/blob_test_base.cpp index 970ce2c4..053a0af2 100644 --- a/Microsoft.WindowsAzure.Storage/tests/blob_test_base.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/blob_test_base.cpp @@ -23,19 +23,6 @@ #include "wascore/util.h" -void blob_service_test_base::fill_buffer(std::vector& buffer) -{ - fill_buffer(buffer, 0, buffer.size()); -} - -void blob_service_test_base::fill_buffer(std::vector& buffer, size_t offset, size_t count) -{ - std::generate_n(buffer.begin() + offset, count, []() -> uint8_t - { - return uint8_t(std::rand()); - }); -} - utility::string_t blob_service_test_base::fill_buffer_and_get_md5(std::vector& buffer) { return fill_buffer_and_get_md5(buffer, 0, buffer.size()); @@ -72,8 +59,8 @@ utility::string_t blob_service_test_base::get_random_container_name(size_t lengt name.resize(length); std::generate_n(name.begin(), length, [] () -> utility::char_t { - const utility::char_t possible_chars[] = { _XPLATSTR("abcdefghijklmnopqrstuvwxyz1234567890") }; - return possible_chars[std::rand() % (sizeof(possible_chars) / sizeof(utility::char_t) - 1)]; + const utility::string_t possible_chars = _XPLATSTR("abcdefghijklmnopqrstuvwxyz1234567890"); + return possible_chars[get_random_int32() % possible_chars.length()]; }); return azure::storage::core::convert_to_string(utility::datetime::utc_now().to_interval()) + name; diff --git a/Microsoft.WindowsAzure.Storage/tests/blob_test_base.h b/Microsoft.WindowsAzure.Storage/tests/blob_test_base.h index 68e9c9c9..60f27549 100644 --- a/Microsoft.WindowsAzure.Storage/tests/blob_test_base.h +++ b/Microsoft.WindowsAzure.Storage/tests/blob_test_base.h @@ -47,8 +47,6 @@ class blob_service_test_base : public test_base protected: static web::http::uri defiddler(const web::http::uri& uri); - static void fill_buffer(std::vector& buffer); - static void fill_buffer(std::vector& buffer, size_t offset, size_t count); static utility::string_t fill_buffer_and_get_md5(std::vector& buffer); static utility::string_t fill_buffer_and_get_crc64(std::vector& buffer); static utility::string_t fill_buffer_and_get_md5(std::vector& buffer, size_t offset, size_t count); diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_append_blob_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_append_blob_test.cpp index 82800d7a..352be3f7 100644 --- a/Microsoft.WindowsAzure.Storage/tests/cloud_append_blob_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/cloud_append_blob_test.cpp @@ -874,7 +874,7 @@ SUITE(Blob) try { auto task_result = m_blob.create_or_replace_async(azure::storage::access_condition(), options, m_context, cancel_token_src.get_token()); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); //sleep for sometime before canceling the request and see result. + std::this_thread::sleep_for(std::chrono::milliseconds(30)); //sleep for sometime before canceling the request and see result. cancel_token_src.cancel(); task_result.get(); } diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_blob_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_blob_test.cpp index edea2fd4..d71a650b 100644 --- a/Microsoft.WindowsAzure.Storage/tests/cloud_blob_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/cloud_blob_test.cpp @@ -54,7 +54,7 @@ azure::storage::operation_context blob_test_base::upload_and_download(azure::sto std::vector buffer; buffer.resize(buffer_size); size_t target_blob_size = blob_size == 0 ? buffer_size - buffer_offset : blob_size; - auto md5 = fill_buffer_and_get_md5(buffer, buffer_offset, target_blob_size); + auto md5 = fill_buffer_and_get_md5(buffer, buffer_offset, std::min(target_blob_size, buffer.size() - buffer_offset)); concurrency::streams::istream stream; if (use_seekable_stream) @@ -794,7 +794,7 @@ SUITE(Blob) for (size_t i = 0; i < 2; ++i) { auto file_name = this->get_random_string(); - auto share = test_config::instance().account().create_cloud_file_client().get_share_reference(_XPLATSTR("testshare")); + auto share = test_config::instance().account().create_cloud_file_client().get_share_reference(_XPLATSTR("testshare") + get_random_string()); share.create_if_not_exists(); auto source = share.get_root_directory_reference().get_file_reference(file_name); source.upload_text(_XPLATSTR("1"), azure::storage::file_access_condition(), azure::storage::file_request_options(), m_context); @@ -812,6 +812,7 @@ SUITE(Blob) CHECK(wait_for_copy(dest)); CHECK_THROW(dest.abort_copy(copy_id, azure::storage::access_condition(), azure::storage::blob_request_options(), m_context), azure::storage::storage_exception); CHECK_EQUAL(web::http::status_codes::Conflict, m_context.request_results().back().http_status_code()); + share.delete_share(); } } @@ -892,7 +893,7 @@ SUITE(Blob) azure::storage::operation_context context; concurrency::streams::container_buffer> download_buffer; - utility::size64_t actual_offset = rand() % 255 + 1; + utility::size64_t actual_offset = get_random_int32() % 255 + 1; utility::size64_t actual_length = target_length - actual_offset; blob.download_range_to_stream(download_buffer.create_ostream(), actual_offset, actual_length, azure::storage::access_condition(), option, context); @@ -920,7 +921,7 @@ SUITE(Blob) azure::storage::operation_context context; concurrency::streams::container_buffer> download_buffer; - utility::size64_t actual_offset = rand() % 255 + 1; + utility::size64_t actual_offset = get_random_int32() % 255 + 1; utility::size64_t actual_length = target_length - actual_offset; blob.download_range_to_stream(download_buffer.create_ostream(), actual_offset, std::numeric_limits::max(), azure::storage::access_condition(), option, context); @@ -954,7 +955,7 @@ SUITE(Blob) azure::storage::operation_context context; concurrency::streams::container_buffer> download_buffer; - utility::size64_t actual_offset = rand() % 255 + 1; + utility::size64_t actual_offset = get_random_int32() % 255 + 1; utility::size64_t actual_length = target_length - actual_offset; blob.download_range_to_stream(download_buffer.create_ostream(), actual_offset, actual_length * 2, azure::storage::access_condition(), option, context); diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_block_blob_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_block_blob_test.cpp index 5a29b120..b58ab55f 100644 --- a/Microsoft.WindowsAzure.Storage/tests/cloud_block_blob_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/cloud_block_blob_test.cpp @@ -1381,7 +1381,7 @@ SUITE(Blob) try { auto task_result = m_blob.delete_blob_if_exists_async(azure::storage::delete_snapshots_option::include_snapshots, azure::storage::access_condition(), options, m_context, cancel_token_src.get_token()); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); //sleep for sometime before canceling the request and see result. + std::this_thread::sleep_for(std::chrono::milliseconds(30)); //sleep for sometime before canceling the request and see result. cancel_token_src.cancel(); task_result.get(); } @@ -1610,7 +1610,7 @@ SUITE(Blob) { auto options = azure::storage::blob_request_options(); - options.set_maximum_execution_time(std::chrono::milliseconds(10000)); + options.set_maximum_execution_time(std::chrono::seconds(20)); std::string ex_msg; @@ -1735,7 +1735,7 @@ SUITE(Blob) auto task_result = m_blob.open_write_async(azure::storage::access_condition(), options, m_context, cancel_token_src.get_token()); auto os = task_result.get(); os.streambuf().putn_nocopy(buffer.data(), buffer.size()).wait(); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); //sleep for sometime before canceling the request and see result. + std::this_thread::sleep_for(std::chrono::milliseconds(30)); //sleep for sometime before canceling the request and see result. cancel_token_src.cancel(); os.close().get(); } diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_file_share_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_file_share_test.cpp index d9e1d9c4..87862886 100644 --- a/Microsoft.WindowsAzure.Storage/tests/cloud_file_share_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/cloud_file_share_test.cpp @@ -45,7 +45,7 @@ SUITE(File) TEST_FIXTURE(file_share_test_base, share_create_delete_with_quotas) { - size_t quota = rand() % 5120 + 1; + size_t quota = get_random_int32() % 5120 + 1; CHECK(!m_share.exists(azure::storage::file_request_options(), m_context)); CHECK(!m_share.delete_share_if_exists(azure::storage::file_access_condition(), azure::storage::file_request_options(), m_context)); diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_file_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_file_test.cpp index d4f81eea..16249adf 100644 --- a/Microsoft.WindowsAzure.Storage/tests/cloud_file_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/cloud_file_test.cpp @@ -390,7 +390,7 @@ SUITE(File) for (size_t i = 0; i < 2; ++i) { auto blob_name = this->get_random_string(); - auto container = test_config::instance().account().create_cloud_blob_client().get_container_reference(_XPLATSTR("container")); + auto container = test_config::instance().account().create_cloud_blob_client().get_container_reference(_XPLATSTR("container") + get_random_string()); container.create_if_not_exists(); auto source = container.get_block_blob_reference(blob_name); @@ -411,6 +411,8 @@ SUITE(File) CHECK(wait_for_copy(dest)); CHECK_THROW(dest.abort_copy(copy_id, azure::storage::file_access_condition(), azure::storage::file_request_options(), m_context), azure::storage::storage_exception); CHECK_EQUAL(web::http::status_codes::Conflict, m_context.request_results().back().http_status_code()); + + container.delete_container(); } } @@ -724,10 +726,7 @@ SUITE(File) option.set_parallelism_factor(2); std::vector data; data.resize(target_length); - for (size_t i = 0; i < target_length; ++i) - { - data[i] = i % 255; - } + fill_buffer(data); concurrency::streams::container_buffer> upload_buffer(data); file.upload_from_stream(upload_buffer.create_istream(), azure::storage::file_access_condition(), option, m_context); @@ -735,7 +734,7 @@ SUITE(File) azure::storage::operation_context context; concurrency::streams::container_buffer> download_buffer; - utility::size64_t actual_offset = rand() % 255 + 1; + utility::size64_t actual_offset = get_random_int32() % 255 + 1; utility::size64_t actual_length = target_length - actual_offset; file.download_range_to_stream(download_buffer.create_ostream(), actual_offset, actual_length, azure::storage::file_access_condition(), option, context); @@ -755,10 +754,7 @@ SUITE(File) option.set_parallelism_factor(2); std::vector data; data.resize(target_length); - for (size_t i = 0; i < target_length; ++i) - { - data[i] = i % 255; - } + fill_buffer(data); concurrency::streams::container_buffer> upload_buffer(data); file.upload_from_stream(upload_buffer.create_istream(), azure::storage::file_access_condition(), option, m_context); @@ -766,7 +762,7 @@ SUITE(File) azure::storage::operation_context context; concurrency::streams::container_buffer> download_buffer; - utility::size64_t actual_offset = rand() % 255 + 1; + utility::size64_t actual_offset = get_random_int32() % 255 + 1; utility::size64_t actual_length = target_length - actual_offset; file.download_range_to_stream(download_buffer.create_ostream(), actual_offset, std::numeric_limits::max(), azure::storage::file_access_condition(), option, context); @@ -792,10 +788,7 @@ SUITE(File) option.set_parallelism_factor(10); std::vector data; data.resize(target_length); - for (size_t i = 0; i < target_length; ++i) - { - data[i] = i % 255; - } + fill_buffer(data); concurrency::streams::container_buffer> upload_buffer(data); file.upload_from_stream(upload_buffer.create_istream(), azure::storage::file_access_condition(), option, m_context); @@ -803,7 +796,7 @@ SUITE(File) azure::storage::operation_context context; concurrency::streams::container_buffer> download_buffer; - utility::size64_t actual_offset = rand() % 255 + 1; + utility::size64_t actual_offset = get_random_int32() % 255 + 1; utility::size64_t actual_length = target_length - actual_offset; file.download_range_to_stream(download_buffer.create_ostream(), actual_offset, actual_length * 2, azure::storage::file_access_condition(), option, context); @@ -887,4 +880,4 @@ SUITE(File) check_parallelism(context, 1); CHECK(file.properties().size() == target_length); } -} \ No newline at end of file +} diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_page_blob_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_page_blob_test.cpp index d06c6d2e..96ed3119 100644 --- a/Microsoft.WindowsAzure.Storage/tests/cloud_page_blob_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/cloud_page_blob_test.cpp @@ -1172,7 +1172,7 @@ SUITE(Blob) try { auto task_result = m_blob.create_async(1024, azure::storage::premium_blob_tier::unknown, 0, azure::storage::access_condition(), options, m_context, cancel_token_src.get_token()); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); //sleep for sometime before canceling the request and see result. + std::this_thread::sleep_for(std::chrono::milliseconds(30)); //sleep for sometime before canceling the request and see result. cancel_token_src.cancel(); task_result.get(); } @@ -1528,7 +1528,7 @@ SUITE(Blob) auto task_result = m_blob.open_write_async(azure::storage::access_condition(), options, m_context, cancel_token_src.get_token()); auto os = task_result.get(); os.streambuf().putn_nocopy(buffer.data(), buffer.size()).wait(); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); //sleep for sometime before canceling the request and see result. + std::this_thread::sleep_for(std::chrono::milliseconds(30)); //sleep for sometime before canceling the request and see result. cancel_token_src.cancel(); os.close().get(); } diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_storage_account_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_storage_account_test.cpp index 14290ce5..c74a6fb7 100644 --- a/Microsoft.WindowsAzure.Storage/tests/cloud_storage_account_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/cloud_storage_account_test.cpp @@ -17,6 +17,9 @@ #include "stdafx.h" +#include +#include + #include "test_base.h" #include "check_macros.h" #include "was/storage_account.h" @@ -906,22 +909,31 @@ SUITE(Core) TEST_FIXTURE(test_base, account_sas_permission) { - auto account = test_config::instance().account(); + auto check_account_permission = [](int i) { + auto account = test_config::instance().account(); - azure::storage::account_shared_access_policy policy; - policy.set_expiry(utility::datetime::utc_now() + utility::datetime::from_minutes(90)); - policy.set_address_or_range(azure::storage::shared_access_policy::ip_address_or_range(_XPLATSTR("0.0.0.0"), _XPLATSTR("255.255.255.255"))); - policy.set_protocol(azure::storage::account_shared_access_policy::protocols::https_or_http); - policy.set_service_type((azure::storage::account_shared_access_policy::service_types)0xF); - policy.set_resource_type((azure::storage::account_shared_access_policy::resource_types)0x7); + azure::storage::account_shared_access_policy policy; + policy.set_expiry(utility::datetime::utc_now() + utility::datetime::from_minutes(90)); + policy.set_address_or_range(azure::storage::shared_access_policy::ip_address_or_range(_XPLATSTR("0.0.0.0"), _XPLATSTR("255.255.255.255"))); + policy.set_protocol(azure::storage::account_shared_access_policy::protocols::https_or_http); + policy.set_service_type((azure::storage::account_shared_access_policy::service_types)0xF); + policy.set_resource_type((azure::storage::account_shared_access_policy::resource_types)0x7); - for (int i = 1; i < 0x100; i++) - { policy.set_permissions((uint8_t)i); check_account_sas_permission_blob(account, policy); check_account_sas_permission_queue(account, policy); check_account_sas_permission_table(account, policy); check_account_sas_permission_file(account, policy); + }; + + std::vector> results; + for (int i = 1; i < 0x100; ++i) + { + results.emplace_back(std::async(check_account_permission, i)); + } + for (const auto& r : results) + { + r.wait(); } } diff --git a/Microsoft.WindowsAzure.Storage/tests/file_test_base.cpp b/Microsoft.WindowsAzure.Storage/tests/file_test_base.cpp index 559dfe02..912d2d36 100644 --- a/Microsoft.WindowsAzure.Storage/tests/file_test_base.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/file_test_base.cpp @@ -27,8 +27,8 @@ utility::string_t file_service_test_base::get_random_share_name(size_t length) name.resize(length); std::generate_n(name.begin(), length, []() -> utility::char_t { - const utility::char_t possible_chars[] = { _XPLATSTR("abcdefghijklmnopqrstuvwxyz1234567890") }; - return possible_chars[std::rand() % (sizeof(possible_chars) / sizeof(utility::char_t) - 1)]; + const utility::string_t possible_chars = _XPLATSTR("abcdefghijklmnopqrstuvwxyz1234567890"); + return possible_chars[get_random_int32() % possible_chars.length()]; }); return azure::storage::core::convert_to_string(utility::datetime::utc_now().to_interval()) + name; @@ -212,4 +212,4 @@ void file_share_test_base::check_access(const utility::string_t& sas_token, uint { CHECK_THROW(file.delete_file(azure::storage::file_access_condition(), azure::storage::file_request_options(), m_context), azure::storage::storage_exception); } -} \ No newline at end of file +} diff --git a/Microsoft.WindowsAzure.Storage/tests/main.cpp b/Microsoft.WindowsAzure.Storage/tests/main.cpp index 2e6f4af9..82b6f8ee 100644 --- a/Microsoft.WindowsAzure.Storage/tests/main.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/main.cpp @@ -17,6 +17,10 @@ #include "stdafx.h" +#include +#include +#include + #include "was/blob.h" #ifndef _WIN32 @@ -30,17 +34,128 @@ #endif -int run_tests(const char* suite_name, const char* test_name) +class custom_test_reporter : public UnitTest::TestReporter { - UnitTest::TestReporterStdout reporter; - UnitTest::TestRunner runner(reporter); - return runner.RunTestsIf(UnitTest::Test::GetTestList(), suite_name, [test_name] (UnitTest::Test* test) -> bool +public: + custom_test_reporter() : m_reporter(std::make_shared()) {} + ~custom_test_reporter() override {} + + void ReportTestStart(const UnitTest::TestDetails& test) override + { + m_reporter->ReportTestStart(test); + } + + void ReportFailure(const UnitTest::TestDetails& test, char const* failure) override { - return (test_name == NULL) || (!strcmp(test_name, test->m_details.testName)); - }, 0); + std::string suite_name = test.suiteName; + std::string test_name = test.testName; + std::string full_name = suite_name + ":" + test_name; + if (m_failed_tests.empty() || m_failed_tests.back() != full_name) + { + m_failed_tests.emplace_back(full_name); + } + m_reporter->ReportFailure(test, failure); + } + + void ReportTestFinish(const UnitTest::TestDetails& test, float secondsElapsed) override + { + m_reporter->ReportTestFinish(test, secondsElapsed); + } + + void ReportSummary(int totalTestCount, int failedTestCount, int failureCount, float secondsElapsed) override + { + m_reporter->ReportSummary(totalTestCount, failedTestCount, failureCount, secondsElapsed); + } + + const std::vector& GetFailedTests() const + { + return m_failed_tests; + } + +private: + // Since UnitTest::TestReporterStdout privatized all methods, we cannot directly inherit from it. Use this as a workaround. + std::shared_ptr m_reporter; + std::vector m_failed_tests; +}; + +struct retry_policy +{ + // If m out of n retries succeed, this test case is considered passed. + int m{ 0 }; + int n{ 0 }; +}; + +int run_tests(const std::unordered_set& included_cases, const std::unordered_set& excluded_cases, retry_policy retry_policy, const std::string& warning_message_prefix) +{ + std::unordered_map failed_testcases; + { + custom_test_reporter reporter; + UnitTest::TestRunner runner(reporter); + + auto match = [](const std::unordered_set& all_cases, const std::string& suite_name, const std::string& test_name) + { + return all_cases.find(suite_name) != all_cases.end() || all_cases.find(suite_name + ":" + test_name) != all_cases.end(); + }; + + runner.RunTestsIf(UnitTest::Test::GetTestList(), nullptr, [match, included_cases, excluded_cases](const UnitTest::Test* test) -> bool + { + std::string suite_name = test->m_details.suiteName; + std::string test_name = test->m_details.testName; + + return !match(excluded_cases, suite_name, test_name) && (included_cases.empty() || match(included_cases, suite_name, test_name)); + }, 0); + + if (retry_policy.m > 0) + { + for (const auto& t : reporter.GetFailedTests()) + { + failed_testcases.emplace(t, 0); + } + } + } + + for (int i = 0; i < retry_policy.n && !failed_testcases.empty(); ++i) + { + custom_test_reporter reporter; + UnitTest::TestRunner runner(reporter); + + runner.RunTestsIf(UnitTest::Test::GetTestList(), nullptr, [&failed_testcases, i, retry_policy](const UnitTest::Test* test) -> bool + { + std::string suite_name = test->m_details.suiteName; + std::string test_name = test->m_details.testName; + std::string full_name = suite_name + ":" + test_name; + + auto ite = failed_testcases.find(full_name); + if (ite != failed_testcases.end()) + { + int failed_count = ite->second; + int successful_count = i - failed_count; + return successful_count < retry_policy.m && failed_count < retry_policy.n - retry_policy.m + 1; + } + return false; + }, 0); + + for (const auto& t : reporter.GetFailedTests()) + { + ++failed_testcases[t]; + } + } + + int num_failed = 0; + for (const auto& p : failed_testcases) + { + fprintf(stderr, "%s%s failed %d time(s)\n", warning_message_prefix.data(), p.first.data(), p.second + 1); + + if (p.second > retry_policy.n - retry_policy.m) + { + ++num_failed; + } + } + + return num_failed; } -int main(int argc, const char* argv[]) +int main(int argc, const char** argv) { azure::storage::operation_context::set_default_log_level(azure::storage::client_log_level::log_level_verbose); @@ -58,30 +173,59 @@ int main(int argc, const char* argv[]) #endif - int failure_count; - if (argc == 1) + std::unordered_set included_cases; + std::unordered_set excluded_cases; + retry_policy retry_policy; + std::string warning_message_prefix; + + auto starts_with = [](const std::string& str, const std::string& prefix) { - failure_count = run_tests(NULL, NULL); - } - else + size_t i = 0; + while (i < str.length() && i < prefix.length() && prefix[i] == str[i]) ++i; + return i == prefix.length(); + }; + + auto add_to = [](std::unordered_set& all_cases, const std::string& name) + { + auto colon_pos = name.find(":"); + std::string suite_name = name.substr(0, colon_pos); + if (suite_name.empty()) + { + throw std::invalid_argument("Invalid test case \"" + name + "\"."); + } + all_cases.emplace(name); + }; + + for (int i = 1; i < argc; ++i) { - failure_count = 0; - for (int i = 1; i < argc; ++i) + std::string arg(argv[i]); + if (starts_with(arg, "--retry-policy=")) { - std::string arg(argv[i]); - auto colon = arg.find(':'); - if (colon == std::string::npos) + size_t pos; + std::string policy_str = arg.substr(arg.find('=') + 1); + retry_policy.m = std::stoi(policy_str, &pos); + if (pos != policy_str.size()) { - failure_count += run_tests(argv[i], NULL); + retry_policy.n = std::stoi(policy_str.substr(pos + 1)); } else { - auto suite_name = arg.substr(0, colon); - auto test_name = arg.substr(colon + 1); - failure_count += run_tests(suite_name.c_str(), test_name.c_str()); + retry_policy.n = retry_policy.m; } } + else if (starts_with(arg, "--warning-message=")) + { + warning_message_prefix = arg.substr(arg.find('=') + 1); + } + else if (starts_with(arg, "--exclude=")) + { + add_to(excluded_cases, arg.substr(arg.find('=') + 1)); + } + else + { + add_to(included_cases, arg); + } } - return failure_count; + return run_tests(included_cases, excluded_cases, retry_policy, warning_message_prefix); } diff --git a/Microsoft.WindowsAzure.Storage/tests/read_from_secondary_test.cpp b/Microsoft.WindowsAzure.Storage/tests/read_from_secondary_test.cpp index 5458eb9e..b01a5909 100644 --- a/Microsoft.WindowsAzure.Storage/tests/read_from_secondary_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/read_from_secondary_test.cpp @@ -101,7 +101,8 @@ class multi_location_test_helper // This check assumes that datetime::to_interval() returns the time in microseconds/10 std::chrono::microseconds interval((m_context.request_results()[m_context_results_offset + i + 1].start_time().to_interval() - m_context.request_results()[m_context_results_offset + i].end_time().to_interval()) / 10); - CHECK(m_retry_info_list[i].retry_interval() < interval); + const std::chrono::milliseconds deviation(1); + CHECK(m_retry_info_list[i].retry_interval() - deviation < interval); } } diff --git a/Microsoft.WindowsAzure.Storage/tests/result_iterator_test.cpp b/Microsoft.WindowsAzure.Storage/tests/result_iterator_test.cpp index 2fda4a93..251e6693 100644 --- a/Microsoft.WindowsAzure.Storage/tests/result_iterator_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/result_iterator_test.cpp @@ -59,7 +59,7 @@ class test_result_provider if (!m_return_full_segment) { // return less results - res_segment_size = std::rand() % (res_segment_size + 1); + res_segment_size = get_random_int32() % (res_segment_size + 1); } std::vector res_vec; diff --git a/Microsoft.WindowsAzure.Storage/tests/test_base.cpp b/Microsoft.WindowsAzure.Storage/tests/test_base.cpp index 7c0994fc..9578f42b 100644 --- a/Microsoft.WindowsAzure.Storage/tests/test_base.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/test_base.cpp @@ -17,11 +17,39 @@ #include "stdafx.h" +#include +#include + #include "test_base.h" #include "cpprest/json.h" +static thread_local std::mt19937_64 random_generator(std::random_device{}()); + +bool get_random_boolean() +{ + std::uniform_int_distribution distribution(0, 1); + return distribution(random_generator) == 0; +} + +int32_t get_random_int32() +{ + std::uniform_int_distribution distribution(0, std::numeric_limits::max()); + return distribution(random_generator); +} + +int64_t get_random_int64() +{ + std::uniform_int_distribution distribution(0LL, std::numeric_limits::max()); + return distribution(random_generator); +} + +double get_random_double() +{ + std::uniform_real_distribution distribution(0, 1.0); + return distribution(random_generator); +} + utility::string_t test_base::object_name_prefix = utility::string_t(_XPLATSTR("nativeclientlibraryunittest")); -bool test_base::is_random_initialized = false; test_config::test_config() { @@ -116,83 +144,58 @@ utility::string_t test_base::get_string(utility::char_t value1, utility::char_t return result.str(); } -void test_base::initialize_random() +utility::string_t test_base::get_random_string(const std::vector& charset, size_t size) { - if (!is_random_initialized) - { - srand((unsigned int)time(NULL)); - is_random_initialized = true; - } -} - -bool test_base::get_random_boolean() -{ - initialize_random(); - return (rand() & 0x1) == 0; -} - -int32_t test_base::get_random_int32() -{ - initialize_random(); - return (int32_t)rand() << 16 | (int32_t)rand(); -} - -int64_t test_base::get_random_int64() -{ - initialize_random(); - return (int64_t)rand() << 48 | (int64_t)rand() << 32 | (int64_t)rand() << 16 | (int64_t)rand(); -} - -double test_base::get_random_double() -{ - initialize_random(); - return (double)rand() / RAND_MAX; -} - -utility::string_t test_base::get_random_string(const std::vector charset, size_t size) -{ - initialize_random(); utility::string_t result; result.reserve(size); + std::uniform_int_distribution distribution(0, charset.size() - 1); for (size_t i = 0; i < size; ++i) { - result.push_back(charset[rand() % charset.size()]); + result.push_back(charset[distribution(random_generator)]); } - return result; } utility::string_t test_base::get_random_string(size_t size) { - initialize_random(); - utility::string_t result; - result.reserve(size); - for (size_t i = 0; i < size; ++i) - { - result.push_back((utility::char_t) (_XPLATSTR('0') + rand() % 10)); - } - return result; + const static std::vector charset { + _XPLATSTR('0'), _XPLATSTR('1'), _XPLATSTR('2'), _XPLATSTR('3'), _XPLATSTR('4'), + _XPLATSTR('5'), _XPLATSTR('6'), _XPLATSTR('7'), _XPLATSTR('8'), _XPLATSTR('9'), + }; + return get_random_string(charset, size); } utility::datetime test_base::get_random_datetime() { - initialize_random(); - return utility::datetime::utc_now() + rand(); + return utility::datetime::utc_now() + get_random_int32(); } std::vector test_base::get_random_binary_data() { - initialize_random(); const int SIZE = 100; std::vector result; result.reserve(SIZE); + std::uniform_int_distribution distribution(std::numeric_limits::min(), std::numeric_limits::max()); for (int i = 0; i < SIZE; ++i) { - result.push_back((unsigned char)(rand() % 256)); + result.push_back(uint8_t(distribution(random_generator))); } return result; } +void test_base::fill_buffer(std::vector& buffer) +{ + fill_buffer(buffer, 0, buffer.size()); +} + +void test_base::fill_buffer(std::vector& buffer, size_t offset, size_t count) +{ + std::generate_n(buffer.begin() + offset, count, []() -> uint8_t + { + return uint8_t(get_random_int32()); + }); +} + utility::uuid test_base::get_random_guid() { return utility::new_uuid(); diff --git a/Microsoft.WindowsAzure.Storage/tests/test_base.h b/Microsoft.WindowsAzure.Storage/tests/test_base.h index 10f1b689..8dacb494 100644 --- a/Microsoft.WindowsAzure.Storage/tests/test_base.h +++ b/Microsoft.WindowsAzure.Storage/tests/test_base.h @@ -26,6 +26,11 @@ #define OPERATION_CANCELED "Operation canceled" #endif +bool get_random_boolean(); +int32_t get_random_int32(); +int64_t get_random_int64(); +double get_random_double(); + class test_config { public: @@ -81,29 +86,24 @@ class test_base azure::storage::operation_context m_context; static utility::string_t object_name_prefix; - static bool is_random_initialized; public: static utility::datetime parse_datetime(const utility::string_t& value, utility::datetime::date_format format = utility::datetime::date_format::RFC_1123); static utility::string_t get_string(utility::char_t value1, utility::char_t value2); - static void initialize_random(); - static bool get_random_boolean(); - static int32_t get_random_int32(); - static int64_t get_random_int64(); - static double get_random_double(); - static utility::string_t get_random_string(const std::vector charset, size_t size); + static utility::string_t get_random_string(const std::vector& charset, size_t size); static utility::string_t get_random_string(size_t size = 10); static utility::datetime get_random_datetime(); static std::vector get_random_binary_data(); + static void fill_buffer(std::vector& buffer); + static void fill_buffer(std::vector& buffer, size_t offset, size_t count); static utility::uuid get_random_guid(); static utility::string_t get_object_name(const utility::string_t& object_type_name); template static TEnum get_random_enum(TEnum max_enum_value) { - initialize_random(); - return static_cast(rand() % (static_cast(max_enum_value)+1)); + return static_cast(get_random_int32() % (static_cast(max_enum_value) + 1)); } template