github.com/goravel/framework@v1.13.9/schedule/application_test.go (about)

     1  package schedule
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/stretchr/testify/mock"
     9  	"github.com/stretchr/testify/suite"
    10  
    11  	cachemocks "github.com/goravel/framework/contracts/cache/mocks"
    12  	consolemocks "github.com/goravel/framework/contracts/console/mocks"
    13  	logmocks "github.com/goravel/framework/contracts/log/mocks"
    14  	"github.com/goravel/framework/contracts/schedule"
    15  	"github.com/goravel/framework/support/carbon"
    16  )
    17  
    18  type ApplicationTestSuite struct {
    19  	suite.Suite
    20  }
    21  
    22  func TestApplicationTestSuite(t *testing.T) {
    23  	suite.Run(t, new(ApplicationTestSuite))
    24  }
    25  
    26  func (s *ApplicationTestSuite) SetupTest() {
    27  }
    28  
    29  func (s *ApplicationTestSuite) TestCallAndCommand() {
    30  	mockArtisan := &consolemocks.Artisan{}
    31  	mockArtisan.On("Call", "test --name Goravel argument0 argument1").Return().Times(3)
    32  
    33  	mockLog := &logmocks.Log{}
    34  	mockLog.On("Error", "panic", mock.Anything).Return().Times(3)
    35  
    36  	immediatelyCall := 0
    37  	delayIfStillRunningCall := 0
    38  	skipIfStillRunningCall := 0
    39  
    40  	app := NewApplication(mockArtisan, nil, mockLog)
    41  	app.Register([]schedule.Event{
    42  		app.Call(func() {
    43  			panic(1)
    44  		}).EveryMinute(),
    45  		app.Call(func() {
    46  			immediatelyCall++
    47  		}).EveryMinute(),
    48  		app.Call(func() {
    49  			time.Sleep(61 * time.Second)
    50  			delayIfStillRunningCall++
    51  		}).EveryMinute().DelayIfStillRunning(),
    52  		app.Call(func() {
    53  			time.Sleep(61 * time.Second)
    54  			skipIfStillRunningCall++
    55  		}).EveryMinute().SkipIfStillRunning(),
    56  		app.Command("test --name Goravel argument0 argument1").EveryMinute(),
    57  	})
    58  
    59  	second := carbon.Now().Second()
    60  	// Make sure run 3 times
    61  	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(120+6+60-second)*time.Second)
    62  	defer cancel()
    63  	go func(ctx context.Context) {
    64  		app.Run()
    65  
    66  		for range ctx.Done() {
    67  			return
    68  		}
    69  	}(ctx)
    70  
    71  	time.Sleep(time.Duration(120+5+60-second) * time.Second)
    72  	app.cron.Stop()
    73  
    74  	s.Equal(3, immediatelyCall)
    75  	s.Equal(2, delayIfStillRunningCall)
    76  	s.Equal(1, skipIfStillRunningCall)
    77  	mockArtisan.AssertExpectations(s.T())
    78  	mockLog.AssertExpectations(s.T())
    79  }
    80  
    81  func (s *ApplicationTestSuite) TestOnOneServer() {
    82  	mockArtisan := &consolemocks.Artisan{}
    83  	mockArtisan.On("Call", "test --name Goravel argument0 argument1").Return().Twice()
    84  
    85  	now := carbon.Now().AddMinute()
    86  	mockCache := &cachemocks.Cache{}
    87  	mockLock := &cachemocks.Lock{}
    88  	mockCache.On("Lock", "immediately"+now.Format("Hi"), 1*time.Hour).Return(mockLock).Once()
    89  	mockLock.On("Get").Return(true).Once()
    90  	mockLock = &cachemocks.Lock{}
    91  	mockCache.On("Lock", "immediately"+now.AddMinute().Format("Hi"), 1*time.Hour).Return(mockLock).Once()
    92  	mockLock.On("Get").Return(true).Once()
    93  	mockLock = &cachemocks.Lock{}
    94  	mockCache.On("Lock", "test --name Goravel argument0 argument1"+now.Format("Hi"), 1*time.Hour).Return(mockLock).Once()
    95  	mockLock.On("Get").Return(true).Once()
    96  	mockLock = &cachemocks.Lock{}
    97  	mockCache.On("Lock", "test --name Goravel argument0 argument1"+now.AddMinute().Format("Hi"), 1*time.Hour).Return(mockLock).Once()
    98  	mockLock.On("Get").Return(true).Once()
    99  
   100  	mockCache1 := &cachemocks.Cache{}
   101  	mockLock1 := &cachemocks.Lock{}
   102  	mockCache1.On("Lock", "immediately"+now.Format("Hi"), 1*time.Hour).Return(mockLock1).Once()
   103  	mockLock1.On("Get").Return(false).Once()
   104  	mockLock1 = &cachemocks.Lock{}
   105  	mockCache1.On("Lock", "immediately"+now.AddMinute().Format("Hi"), 1*time.Hour).Return(mockLock1).Once()
   106  	mockLock1.On("Get").Return(false).Once()
   107  	mockLock1 = &cachemocks.Lock{}
   108  	mockCache1.On("Lock", "test --name Goravel argument0 argument1"+now.Format("Hi"), 1*time.Hour).Return(mockLock1).Once()
   109  	mockLock1.On("Get").Return(false).Once()
   110  	mockLock1 = &cachemocks.Lock{}
   111  	mockCache1.On("Lock", "test --name Goravel argument0 argument1"+now.AddMinute().Format("Hi"), 1*time.Hour).Return(mockLock1).Once()
   112  	mockLock1.On("Get").Return(false).Once()
   113  
   114  	immediatelyCall := 0
   115  
   116  	app := NewApplication(mockArtisan, mockCache, nil)
   117  	app.Register([]schedule.Event{
   118  		app.Call(func() {
   119  			immediatelyCall++
   120  		}).EveryMinute().OnOneServer().Name("immediately"),
   121  		app.Command("test --name Goravel argument0 argument1").EveryMinute().OnOneServer(),
   122  	})
   123  
   124  	app1 := NewApplication(nil, mockCache1, nil)
   125  	app1.Register([]schedule.Event{
   126  		app.Call(func() {
   127  			immediatelyCall++
   128  		}).EveryMinute().OnOneServer().Name("immediately"),
   129  		app.Command("test --name Goravel argument0 argument1").EveryMinute().OnOneServer(),
   130  	})
   131  
   132  	second := carbon.Now().Second()
   133  	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(60+2+60-second)*time.Second)
   134  	defer cancel()
   135  	go func(ctx context.Context) {
   136  		app.Run()
   137  		app1.Run()
   138  
   139  		for range ctx.Done() {
   140  			return
   141  		}
   142  	}(ctx)
   143  
   144  	time.Sleep(time.Duration(60+1+60-second) * time.Second)
   145  	app.cron.Stop()
   146  	app1.cron.Stop()
   147  
   148  	s.Equal(2, immediatelyCall)
   149  	mockArtisan.AssertExpectations(s.T())
   150  	mockCache.AssertExpectations(s.T())
   151  }