Commit d28efea2 authored by Alex Kalugin's avatar Alex Kalugin Committed by Commit Bot

Reset next_gethash_time_ in ResetGetHashErrors

If two parallel gethash requests are running and the first fails but the
second succeeds, then gethash error counters are reset and
next_gethash_time_ is not. In this case all following GetFullHashes
calls (until time is out) does not incur actual network requests and
gethash result is improperly reported as MIN_WAIT_DURATION_ERROR, even
though server did not sent min_wait_duration to the client.

Example steps (implemented in unit test):
- Initiate two separate full hash requests.
- Make the first request fail.
- Make the second request succeed.
- Call GetFullHashes method.
Expected result:
- As long as the second request was successful, the following requests
  are run as usual.
Actual Result:
- Network request is not issued.
- MIN_WAIT_DURATION_ERROR is reported to SafeBrowsing.V4GetHash.Result

Change-Id: Ieeb08046515f87239ec00d9ad13b80c257b59435
Reviewed-on: https://chromium-review.googlesource.com/1119908
Commit-Queue: Alexander Kalugin <akalugin@yandex-team.ru>
Reviewed-by: default avatarVarun Khaneja <vakh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#575928}
parent 562a9c11
...@@ -702,6 +702,7 @@ void V4GetHashProtocolManager::ParseMetadata(const ThreatMatch& match, ...@@ -702,6 +702,7 @@ void V4GetHashProtocolManager::ParseMetadata(const ThreatMatch& match,
void V4GetHashProtocolManager::ResetGetHashErrors() { void V4GetHashProtocolManager::ResetGetHashErrors() {
gethash_error_count_ = 0; gethash_error_count_ = 0;
gethash_back_off_mult_ = 1; gethash_back_off_mult_ = 1;
next_gethash_time_ = base::Time();
} }
void V4GetHashProtocolManager::SetClockForTests(base::Clock* clock) { void V4GetHashProtocolManager::SetClockForTests(base::Clock* clock) {
......
...@@ -221,6 +221,8 @@ class V4GetHashProtocolManager { ...@@ -221,6 +221,8 @@ class V4GetHashProtocolManager {
TestGetHashErrorHandlingNetwork); TestGetHashErrorHandlingNetwork);
FRIEND_TEST_ALL_PREFIXES(V4GetHashProtocolManagerTest, FRIEND_TEST_ALL_PREFIXES(V4GetHashProtocolManagerTest,
TestGetHashErrorHandlingResponseCode); TestGetHashErrorHandlingResponseCode);
FRIEND_TEST_ALL_PREFIXES(V4GetHashProtocolManagerTest,
TestGetHashErrorHandlingParallelRequests);
FRIEND_TEST_ALL_PREFIXES(V4GetHashProtocolManagerTest, GetCachedResults); FRIEND_TEST_ALL_PREFIXES(V4GetHashProtocolManagerTest, GetCachedResults);
FRIEND_TEST_ALL_PREFIXES(V4GetHashProtocolManagerTest, TestUpdatesAreMerged); FRIEND_TEST_ALL_PREFIXES(V4GetHashProtocolManagerTest, TestUpdatesAreMerged);
friend class V4GetHashProtocolManagerTest; friend class V4GetHashProtocolManagerTest;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/simple_test_clock.h" #include "base/test/simple_test_clock.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "components/safe_browsing/db/safebrowsing.pb.h" #include "components/safe_browsing/db/safebrowsing.pb.h"
...@@ -93,6 +94,24 @@ class V4GetHashProtocolManagerTest : public PlatformTest { ...@@ -93,6 +94,24 @@ class V4GetHashProtocolManagerTest : public PlatformTest {
response_code, data); response_code, data);
} }
static void SetupFullHashFetcherToReturnResponse(V4GetHashProtocolManager* pm,
const FullHash& full_hash,
int net_error,
int response_code,
const std::string& data) {
network::SimpleURLLoader* url_loader = nullptr;
for (const auto& pending_request : pm->pending_hash_requests_) {
if (pending_request.second->full_hash_to_store_and_hash_prefixes.count(
full_hash)) {
EXPECT_EQ(nullptr, url_loader);
url_loader = pending_request.second->loader.get();
}
}
ASSERT_TRUE(url_loader);
pm->OnURLLoaderCompleteInternal(url_loader, net_error, response_code, data);
}
static void SetupFetcherToReturnOKResponse( static void SetupFetcherToReturnOKResponse(
V4GetHashProtocolManager* pm, V4GetHashProtocolManager* pm,
const std::vector<ResponseInfo>& infos) { const std::vector<ResponseInfo>& infos) {
...@@ -133,7 +152,8 @@ class V4GetHashProtocolManagerTest : public PlatformTest { ...@@ -133,7 +152,8 @@ class V4GetHashProtocolManagerTest : public PlatformTest {
callback_called_ = true; callback_called_ = true;
} }
bool callback_called() { return callback_called_; } bool callback_called() const { return callback_called_; }
void reset_callback_called() { callback_called_ = false; }
private: private:
static std::string GetV4HashResponse( static std::string GetV4HashResponse(
...@@ -214,6 +234,71 @@ TEST_F(V4GetHashProtocolManagerTest, TestGetHashErrorHandlingResponseCode) { ...@@ -214,6 +234,71 @@ TEST_F(V4GetHashProtocolManagerTest, TestGetHashErrorHandlingResponseCode) {
EXPECT_TRUE(callback_called()); EXPECT_TRUE(callback_called());
} }
TEST_F(V4GetHashProtocolManagerTest, TestGetHashErrorHandlingParallelRequests) {
std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager());
std::vector<FullHashInfo> empty_results;
base::HistogramTester histogram_tester;
FullHashToStoreAndHashPrefixesMap matched_locally1;
matched_locally1[FullHash("AHash1Full")].emplace_back(GetUrlSocEngId(),
HashPrefix("AHash1"));
pm->GetFullHashes(matched_locally1, {},
base::BindRepeating(
&V4GetHashProtocolManagerTest::ValidateGetV4HashResults,
base::Unretained(this), empty_results));
FullHashToStoreAndHashPrefixesMap matched_locally2;
matched_locally2[FullHash("AHash2Full")].emplace_back(GetUrlSocEngId(),
HashPrefix("AHash2"));
pm->GetFullHashes(matched_locally2, {},
base::BindRepeating(
&V4GetHashProtocolManagerTest::ValidateGetV4HashResults,
base::Unretained(this), empty_results));
// Fail the first request.
SetupFullHashFetcherToReturnResponse(pm.get(), FullHash("AHash1Full"),
net::ERR_CONNECTION_RESET, 200,
GetStockV4HashResponse());
// Should have recorded one error, but back off multiplier is unchanged.
EXPECT_EQ(1ul, pm->gethash_error_count_);
EXPECT_EQ(1ul, pm->gethash_back_off_mult_);
EXPECT_TRUE(callback_called());
histogram_tester.ExpectUniqueSample("SafeBrowsing.V4GetHash.Result",
V4OperationResult::NETWORK_ERROR, 1);
reset_callback_called();
// Comple the second request successfully.
SetupFullHashFetcherToReturnResponse(pm.get(), FullHash("AHash2Full"),
net::OK, 200, GetStockV4HashResponse());
// Error counters are reset.
EXPECT_EQ(0ul, pm->gethash_error_count_);
EXPECT_EQ(1ul, pm->gethash_back_off_mult_);
EXPECT_TRUE(callback_called());
histogram_tester.ExpectBucketCount("SafeBrowsing.V4GetHash.Result",
V4OperationResult::STATUS_200, 1);
reset_callback_called();
// Start the third request.
FullHashToStoreAndHashPrefixesMap matched_locally3;
matched_locally3[FullHash("AHash3Full")].emplace_back(GetUrlSocEngId(),
HashPrefix("AHash3"));
pm->GetFullHashes(matched_locally3, {},
base::BindRepeating(
&V4GetHashProtocolManagerTest::ValidateGetV4HashResults,
base::Unretained(this), empty_results));
// The request is not failed right away.
EXPECT_FALSE(callback_called());
// The request is not reported as MIN_WAIT_DURATION_ERROR.
histogram_tester.ExpectBucketCount("SafeBrowsing.V4GetHash.Result",
V4OperationResult::MIN_WAIT_DURATION_ERROR,
0);
}
TEST_F(V4GetHashProtocolManagerTest, TestGetHashErrorHandlingOK) { TEST_F(V4GetHashProtocolManagerTest, TestGetHashErrorHandlingOK) {
std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager()); std::unique_ptr<V4GetHashProtocolManager> pm(CreateProtocolManager());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment