github.com/blend/go-sdk@v1.20220411.3/cron/immediately_then_test.go (about)

     1  /*
     2  
     3  Copyright (c) 2022 - Present. Blend Labs, Inc. All rights reserved
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file.
     5  
     6  */
     7  
     8  package cron
     9  
    10  import (
    11  	"fmt"
    12  	"sync"
    13  	"sync/atomic"
    14  	"testing"
    15  	"time"
    16  
    17  	"github.com/blend/go-sdk/assert"
    18  )
    19  
    20  func Test_Immediately(t *testing.T) {
    21  	t.Parallel()
    22  	its := assert.New(t)
    23  
    24  	ts := time.Date(2019, 9, 8, 12, 11, 10, 9, time.UTC)
    25  
    26  	is := Immediately()
    27  	its.Equal(StringScheduleImmediately, is.String())
    28  	next := is.Next(ts)
    29  	its.NotEqual(ts, next)
    30  	next = is.Next(ts)
    31  	its.True(next.IsZero())
    32  
    33  	thenSchedule := EverySecond()
    34  	is = Immediately().Then(thenSchedule).(*ImmediateSchedule)
    35  	its.Equal(fmt.Sprintf("%s %v", StringScheduleImmediatelyThen, thenSchedule), is.String())
    36  
    37  	next = is.Next(ts)
    38  	its.NotEqual(ts, next)
    39  	its.Equal(1, is.didRun)
    40  
    41  	next = is.Next(ts)
    42  	its.Equal(ts.Add(time.Second), next)
    43  
    44  	// another one to be safe.
    45  	next = is.Next(ts)
    46  	its.Equal(ts.Add(time.Second), next)
    47  	its.Equal(1, is.didRun)
    48  }
    49  
    50  func Test_Immediately_new(t *testing.T) {
    51  	t.Parallel()
    52  	its := assert.New(t)
    53  
    54  	ts := time.Date(2019, 9, 8, 12, 11, 10, 9, time.UTC)
    55  
    56  	is := new(ImmediateSchedule)
    57  	its.Equal(StringScheduleImmediately, is.String())
    58  	next := is.Next(ts)
    59  	its.NotEqual(ts, next)
    60  	next = is.Next(ts)
    61  	its.True(next.IsZero())
    62  
    63  	thenSchedule := EverySecond()
    64  	is = new(ImmediateSchedule).Then(thenSchedule).(*ImmediateSchedule)
    65  	its.Equal(fmt.Sprintf("%s %v", StringScheduleImmediatelyThen, thenSchedule), is.String())
    66  
    67  	next = is.Next(ts)
    68  	its.NotEqual(ts, next)
    69  	its.Equal(1, is.didRun)
    70  
    71  	next = is.Next(ts)
    72  	its.Equal(ts.Add(time.Second), next)
    73  
    74  	// another one to be safe.
    75  	next = is.Next(ts)
    76  	its.Equal(ts.Add(time.Second), next)
    77  	its.Equal(1, is.didRun)
    78  }
    79  
    80  func Test_Immediately_Then(t *testing.T) {
    81  	t.Parallel()
    82  	its := assert.New(t)
    83  
    84  	s := Immediately().Then(EveryHour())
    85  	its.NotNil(s.Next(Zero))
    86  	now := Now()
    87  	next := s.Next(Now())
    88  	its.True(next.Sub(now) > time.Minute, fmt.Sprintf("%v", next.Sub(now)))
    89  	its.True(next.Sub(now) < (2 * time.Hour))
    90  }
    91  
    92  func Test_ImmediateSchedule_parallel(t *testing.T) {
    93  	t.Parallel()
    94  	its := assert.New(t)
    95  
    96  	ts := time.Date(2019, 9, 8, 12, 11, 10, 9, time.UTC)
    97  
    98  	var nextCount int32
    99  	next := ScheduleFunc(func(ts time.Time) time.Time {
   100  		atomic.AddInt32(&nextCount, 1)
   101  		return ts.Add(time.Minute)
   102  	})
   103  
   104  	is := Immediately().Then(next)
   105  
   106  	start := make(chan struct{})
   107  
   108  	now := Now()
   109  	times := make(chan time.Time, 10)
   110  	wg := sync.WaitGroup{}
   111  	wg.Add(10)
   112  	for x := 0; x < 10; x++ {
   113  		go func() {
   114  			defer wg.Done()
   115  			<-start
   116  			out := is.Next(ts)
   117  			times <- out
   118  		}()
   119  	}
   120  
   121  	close(start)
   122  	wg.Wait()
   123  
   124  	var allTimes []time.Time
   125  	for x := 0; x < 10; x++ {
   126  		allTimes = append(allTimes, <-times)
   127  	}
   128  
   129  	its.AnyCount(allTimes, 1, func(v interface{}) bool {
   130  		typed, _ := v.(time.Time)
   131  		return typed.After(now) && typed.Sub(now) < time.Second
   132  	}, "(1) of the times should be '''now''' and the other 9 should have gone through the next schedule")
   133  	its.AnyCount(allTimes, 9, func(v interface{}) bool {
   134  		return v.(time.Time).Equal(ts.Add(time.Minute))
   135  	}, "(1) of the times should be '''now''' and the other 9 should have gone through the next schedule")
   136  }