1d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)#include "chrome/browser/sync/test/integration/retry_verifier.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/engine/polling_constants.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/sessions/sync_session_snapshot.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Given the current delay calculate the minimum and maximum wait times for
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the next retry.
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DelayInfo CalculateDelay(int64 current_delay) {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 backoff_s = std::max(static_cast<int64>(1), current_delay *
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             syncer::kBackoffRandomizationFactor);
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelayInfo delay_info;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delay_info.min_delay = backoff_s + (-1 * current_delay/
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             syncer::kBackoffRandomizationFactor);
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delay_info.max_delay = backoff_s + current_delay/2;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delay_info.min_delay = std::max(static_cast<int64>(1),
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::min(delay_info.min_delay, syncer::kMaxBackoffSeconds));
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delay_info.max_delay = std::max(static_cast<int64>(1),
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::min(delay_info.max_delay, syncer::kMaxBackoffSeconds));
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return delay_info;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Fills the table with the maximum and minimum values for each retry, upto
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |count| number of retries.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FillDelayTable(DelayInfo* delay_table, int count) {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(count > 1);
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We start off with the minimum value of 2 seconds.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delay_table[0].min_delay = static_cast<int64>(2);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delay_table[0].max_delay = static_cast<int64>(2);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 1 ; i < count ; ++i) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delay_table[i].min_delay = CalculateDelay(delay_table[i-1].min_delay).
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               min_delay;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delay_table[i].max_delay = CalculateDelay(delay_table[i-1].max_delay).
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               max_delay;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verifies if the current retry is on time. Note that we dont use the
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// maximum value of the retry range in verifying, only the minimum. Reason
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// being there is no guarantee that the retry will be on the dot. However in
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// practice it is on the dot. But making that assumption for all the platforms
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// would make the test flaky. However we have the global timeout for the
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// verification which would make sure all retries take place in a reasonable
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// amount of time. The global timeout is defined in profile sync service
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// harness as |kExponentialBackoffVerificationTimeoutMs|.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsRetryOnTime(DelayInfo* delay_table, int retry_count,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   const base::TimeDelta& time_elapsed) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Retry Count : " << retry_count
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << " Time elapsed : " << time_elapsed.InSeconds()
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << " Retry table min: " << delay_table[retry_count].min_delay
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << " Retry table max: " << delay_table[retry_count].max_delay;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ((time_elapsed.InSeconds() >= delay_table[retry_count].min_delay));
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RetryVerifier::RetryVerifier() : retry_count_(0),
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 success_(false),
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 done_(false) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&delay_table_, 0, sizeof(delay_table_));
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RetryVerifier::~RetryVerifier() {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Initializes the state for verification.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RetryVerifier::Initialize(
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const syncer::sessions::SyncSessionSnapshot& snap) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  retry_count_ = 0;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_sync_time_ = snap.sync_start_time();
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FillDelayTable(delay_table_, kMaxRetry);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  done_ = false;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  success_ = false;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RetryVerifier::VerifyRetryInterval(
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const syncer::sessions::SyncSessionSnapshot& snap) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(retry_count_ < kMaxRetry);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (retry_count_ == 0) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (snap.sync_start_time() != last_sync_time_) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      retry_count_++;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_sync_time_ = snap.sync_start_time();
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    success_ = true;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if the sync start time has changed. If so indicates a new sync
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // has taken place.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (snap.sync_start_time() != last_sync_time_) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta delta = snap.sync_start_time() - last_sync_time_;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    success_ = IsRetryOnTime(delay_table_,retry_count_ -1, delta);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_sync_time_ = snap.sync_start_time();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++retry_count_;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    done_ = (retry_count_ >= kMaxRetry);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
111d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)
112