Example #1
0
        /// <summary>
        /// <para>@ add</para>
        /// <para>[ start</para>
        /// <para>] end</para>
        /// <para># add + start</para>
        /// <para>$ add + start + end</para>
        /// <para>% start + end</para>
        /// </summary>
        private void ParseAndTest(
            int realTimeToWait,
            params string[] lines)
        {
            int maxSchedulerSleep = ( int ) ( Scheduler.MaxSleepTimeSpan.TotalSeconds );

              TimeService.DebugReplacement = ( ) => this.now;

              Scheduler scheduler = new Scheduler( );

              if ( this.timeoutSpanInSeconds > 0 )
            scheduler.TimeoutSpanInSeconds = this.timeoutSpanInSeconds;

              int? iTimeLineLength = null;

              // for a parameter i, returns time corresponding to the point in the timeline
              // e.g. '@' in "...@." corresponds to (this.now - 1 sec).
              Func<int, DateTime> getTimeFunc =
            i =>
              // ReSharper disable once AccessToModifiedClosure
              // ReSharper disable once PossibleInvalidOperationException
              Now( i - iTimeLineLength.Value + 1 );

              string winningName = null;

              foreach ( string line in lines )
              {
            if ( line.Trim( ).ToLower( ).StartsWith( "time:" ) )
              continue; // line started from "time:" is kind of a comment, ignoring that

            int colIndex = line.IndexOf( ':' );
            if ( colIndex <= 0 )
              throw new Exception( "Cannot find name for: " + line );

            string name =
              line
              .Remove( colIndex )
              .Replace( '*', ' ' )
              .Trim( );

            string timeLine = line.Substring( colIndex + 1 ).ToLower( );

            ForeignId id = GetForeignId( name );

            TrackerStateHolder holder;

            // might be tracker was added by the prev.line:
            scheduler.Trackers.TryGetValue( id, out holder );

            if ( iTimeLineLength == null )
              iTimeLineLength = timeLine.Length;
            else if ( iTimeLineLength != timeLine.Length )
              throw new Exception( "Timelines have different lengths" );

            for ( int i = 0; i < timeLine.Length; i++ )
            {
              char c = timeLine[i];
              // @ add
              // [ call start
              // ] call end
              // s scheduled start

              if ( c == '@' )
              {
            if ( holder != null )
              throw new Exception(
                "Only one '@' per tracker can be found, and it should be first for the tracker: " + id.Id );

            holder = GetHolder( id, getTimeFunc( i ) );
            scheduler.Trackers.Add( id, holder );
              }

              if ( c == '[' ) // holder should be created by now by '@' encountered earlier, otherwise it's NullRefException
            holder.RequestStartTime = getTimeFunc( i );

              if ( c == ']' )
              {
            holder.RefreshTime = getTimeFunc( i );
            holder.Snapshot = CreateMockupSnapshot( holder.RefreshTime.Value );
              }

              if ( c == 's' )
            holder.ScheduledTime = getTimeFunc( i );
            }

            if ( line.Contains( "*" ) )
            {
              if ( winningName != null )
            throw new Exception( "'*' sign (for a winning tracker) specified more than once" );

              winningName = name;
            }

            if ( holder.CurrentRequest == null &&
             holder.RequestStartTime.HasValue &&
             (
                holder.RefreshTime == null ||
                holder.RequestStartTime.Value > holder.RefreshTime.Value
             )
               )
            {
              // just any request to make the field not-null:

              var originalReplacement = TimeService.DebugReplacement;
              try
              {
            TimeService.DebugReplacement = ( ) => holder.RequestStartTime.Value;

            RequestParams requestParams = default( RequestParams );
            requestParams.Id = id.Id;

            holder.CurrentRequest = new FakeLocationRequest( requestParams );
              }
              finally
              {
            TimeService.DebugReplacement = originalReplacement;
              }
            }
            else
            { // need else because it could be set earlier by one of the prev. lines.
              holder.CurrentRequest = null;
            }

            Assert.AreEqual( null, holder.CheckTimesConsistency( ) );
              }

              int expectedSecondsWait = Math.Min( maxSchedulerSleep, realTimeToWait );
              var mockWaitHandle = new MockWaitHandle( expectedSecondsWait * 1000, false );

              IEnumerable<TrackerStateHolder> trackersToRequest = scheduler.ScheduleCleanupWait( mockWaitHandle );

              Assert.IsTrue( mockWaitHandle.IsWaitSucceeded );

              if ( realTimeToWait <= maxSchedulerSleep )
              {
            Assert.AreEqual( 1, trackersToRequest.Count( ) );
            Assert.AreEqual( winningName, trackersToRequest.First( ).ForeignId.Id );
              }
              else
              {
            Assert.AreEqual( 0, trackersToRequest.Count( ) );
              }
        }
Example #2
0
        public void BasicSchedulerTest(
            [Values( 0, 1, 3, 5, 6, 7, 8, 9, 10, 150 )] int sameFeedHitIntervalSeconds
            )
        {
            ForeignAccessCentral.LocationRequestFactories["test"] =
            new MockForeignFactory( )
            {
              MaxCallsInPackCount = 2,
              MinTimeFromPrevStartMs = 2000,
              MinCallsGapMs = 0,
              SameFeedHitIntervalSeconds = sameFeedHitIntervalSeconds
            };

              Scheduler scheduler = new Scheduler( );

              /*
               * time: 09876543210
               *    A: @.....[]...
               *    B: ...@O......
               *
               * Legend:
               * '[' call start
               * ']' succ call end
               * 'O' call started and succ.finished on the same second
               */

              {
            TrackerStateHolder holder = GetHolder( "A", Now( -10 ) );
            holder.RequestStartTime = Now( -4 );
            holder.RefreshTime = Now( -3 );

            scheduler.Trackers.Add( holder.ForeignId, holder );
              }

              {
            TrackerStateHolder holder = GetHolder( "B", Now( -7 ) );
            holder.RequestStartTime = Now( -6 );
            holder.RefreshTime = Now( -6 );

            scheduler.Trackers.Add( holder.ForeignId, holder );
              }

              int maxSchedulerSleep = ( int ) ( Scheduler.MaxSleepTimeSpan.TotalSeconds );

              int realTimeToWait = Math.Max( 0, sameFeedHitIntervalSeconds - 6 );

              int expectedSecondsWait = Math.Min( maxSchedulerSleep, realTimeToWait );

              var mockWaitHandle = new MockWaitHandle( expectedSecondsWait * 1000, false );

              TimeService.DebugReplacement = ( ) => this.now;

              IEnumerable<TrackerStateHolder> trackersToRequest = scheduler.ScheduleCleanupWait( mockWaitHandle );

              Assert.IsTrue( mockWaitHandle.IsWaitSucceeded );

              if ( realTimeToWait <= maxSchedulerSleep )
              {
            Assert.AreEqual( 1, trackersToRequest.Count( ) );
            Assert.AreEqual( "B", trackersToRequest.First( ).ForeignId.Id );
              }
              else
              {
            Assert.AreEqual( 0, trackersToRequest.Count( ) );
              }
        }