github.com/gogf/gf/v2@v2.7.4/os/gcron/gcron_z_unit_test.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/gogf/gf.
     6  
     7  package gcron_test
     8  
     9  import (
    10  	"context"
    11  	"fmt"
    12  	"os"
    13  	"os/signal"
    14  	"syscall"
    15  	"testing"
    16  	"time"
    17  
    18  	"github.com/gogf/gf/v2/container/garray"
    19  	"github.com/gogf/gf/v2/frame/g"
    20  	"github.com/gogf/gf/v2/os/gcron"
    21  	"github.com/gogf/gf/v2/os/glog"
    22  	"github.com/gogf/gf/v2/test/gtest"
    23  )
    24  
    25  var (
    26  	ctx = context.TODO()
    27  )
    28  
    29  func TestCron_Add_Close(t *testing.T) {
    30  	gtest.C(t, func(t *gtest.T) {
    31  		cron := gcron.New()
    32  		array := garray.New(true)
    33  		_, err1 := cron.Add(ctx, "* * * * * *", func(ctx context.Context) {
    34  			g.Log().Print(ctx, "cron1")
    35  			array.Append(1)
    36  		})
    37  		_, err2 := cron.Add(ctx, "* * * * * *", func(ctx context.Context) {
    38  			g.Log().Print(ctx, "cron2")
    39  			array.Append(1)
    40  		}, "test")
    41  		t.Assert(err1, nil)
    42  		t.Assert(err2, nil)
    43  		t.Assert(cron.Size(), 2)
    44  		time.Sleep(1300 * time.Millisecond)
    45  		t.Assert(array.Len(), 2)
    46  		time.Sleep(1300 * time.Millisecond)
    47  		t.Assert(array.Len(), 4)
    48  		cron.Close()
    49  		time.Sleep(1300 * time.Millisecond)
    50  		fixedLength := array.Len()
    51  		time.Sleep(1300 * time.Millisecond)
    52  		t.Assert(array.Len(), fixedLength)
    53  	})
    54  }
    55  
    56  func TestCron_Basic(t *testing.T) {
    57  	gtest.C(t, func(t *gtest.T) {
    58  		cron := gcron.New()
    59  		cron.Add(ctx, "* * * * * *", func(ctx context.Context) {}, "add")
    60  		// fmt.Println("start", time.Now())
    61  		cron.DelayAdd(ctx, time.Second, "* * * * * *", func(ctx context.Context) {}, "delay_add")
    62  		t.Assert(cron.Size(), 1)
    63  		time.Sleep(1200 * time.Millisecond)
    64  		t.Assert(cron.Size(), 2)
    65  
    66  		cron.Remove("delay_add")
    67  		t.Assert(cron.Size(), 1)
    68  
    69  		entry1 := cron.Search("add")
    70  		entry2 := cron.Search("test-none")
    71  		t.AssertNE(entry1, nil)
    72  		t.Assert(entry2, nil)
    73  	})
    74  
    75  	// test @ error
    76  	gtest.C(t, func(t *gtest.T) {
    77  		cron := gcron.New()
    78  		defer cron.Close()
    79  		_, err := cron.Add(ctx, "@aaa", func(ctx context.Context) {}, "add")
    80  		t.AssertNE(err, nil)
    81  	})
    82  
    83  	// test @every error
    84  	gtest.C(t, func(t *gtest.T) {
    85  		cron := gcron.New()
    86  		defer cron.Close()
    87  		_, err := cron.Add(ctx, "@every xxx", func(ctx context.Context) {}, "add")
    88  		t.AssertNE(err, nil)
    89  	})
    90  }
    91  
    92  func TestCron_Remove(t *testing.T) {
    93  	gtest.C(t, func(t *gtest.T) {
    94  		cron := gcron.New()
    95  		array := garray.New(true)
    96  		cron.Add(ctx, "* * * * * *", func(ctx context.Context) {
    97  			array.Append(1)
    98  		}, "add")
    99  		t.Assert(array.Len(), 0)
   100  		time.Sleep(1200 * time.Millisecond)
   101  		t.Assert(array.Len(), 1)
   102  
   103  		cron.Remove("add")
   104  		t.Assert(array.Len(), 1)
   105  		time.Sleep(1200 * time.Millisecond)
   106  		t.Assert(array.Len(), 1)
   107  	})
   108  }
   109  
   110  func TestCron_Add_FixedPattern(t *testing.T) {
   111  	for i := 0; i < 5; i++ {
   112  		doTestCronAddFixedPattern(t)
   113  	}
   114  }
   115  
   116  func doTestCronAddFixedPattern(t *testing.T) {
   117  	gtest.C(t, func(t *gtest.T) {
   118  		var (
   119  			now    = time.Now()
   120  			cron   = gcron.New()
   121  			array  = garray.New(true)
   122  			expect = now.Add(time.Second * 2)
   123  		)
   124  		defer cron.Close()
   125  
   126  		var pattern = fmt.Sprintf(
   127  			`%d %d %d %d %d %s`,
   128  			expect.Second(), expect.Minute(), expect.Hour(), expect.Day(), expect.Month(), expect.Weekday().String(),
   129  		)
   130  		cron.SetLogger(g.Log())
   131  		g.Log().Debugf(ctx, `pattern: %s`, pattern)
   132  		_, err := cron.Add(ctx, pattern, func(ctx context.Context) {
   133  			array.Append(1)
   134  		})
   135  		t.AssertNil(err)
   136  		time.Sleep(3000 * time.Millisecond)
   137  		g.Log().Debug(ctx, `current time`)
   138  		t.Assert(array.Len(), 1)
   139  	})
   140  }
   141  
   142  func TestCron_AddSingleton(t *testing.T) {
   143  	// un used, can be removed
   144  	gtest.C(t, func(t *gtest.T) {
   145  		cron := gcron.New()
   146  		cron.Add(ctx, "* * * * * *", func(ctx context.Context) {}, "add")
   147  		cron.DelayAdd(ctx, time.Second, "* * * * * *", func(ctx context.Context) {}, "delay_add")
   148  		t.Assert(cron.Size(), 1)
   149  		time.Sleep(1200 * time.Millisecond)
   150  		t.Assert(cron.Size(), 2)
   151  
   152  		cron.Remove("delay_add")
   153  		t.Assert(cron.Size(), 1)
   154  
   155  		entry1 := cron.Search("add")
   156  		entry2 := cron.Search("test-none")
   157  		t.AssertNE(entry1, nil)
   158  		t.Assert(entry2, nil)
   159  	})
   160  	// keep this
   161  	gtest.C(t, func(t *gtest.T) {
   162  		cron := gcron.New()
   163  		array := garray.New(true)
   164  		cron.AddSingleton(ctx, "* * * * * *", func(ctx context.Context) {
   165  			array.Append(1)
   166  			time.Sleep(50 * time.Second)
   167  		})
   168  		t.Assert(cron.Size(), 1)
   169  		time.Sleep(3500 * time.Millisecond)
   170  		t.Assert(array.Len(), 1)
   171  	})
   172  
   173  }
   174  
   175  func TestCron_AddOnce1(t *testing.T) {
   176  	gtest.C(t, func(t *gtest.T) {
   177  		cron := gcron.New()
   178  		array := garray.New(true)
   179  		cron.AddOnce(ctx, "* * * * * *", func(ctx context.Context) {
   180  			array.Append(1)
   181  		})
   182  		cron.AddOnce(ctx, "* * * * * *", func(ctx context.Context) {
   183  			array.Append(1)
   184  		})
   185  		t.Assert(cron.Size(), 2)
   186  		time.Sleep(2500 * time.Millisecond)
   187  		t.Assert(array.Len(), 2)
   188  		t.Assert(cron.Size(), 0)
   189  	})
   190  }
   191  
   192  func TestCron_AddOnce2(t *testing.T) {
   193  	gtest.C(t, func(t *gtest.T) {
   194  		cron := gcron.New()
   195  		array := garray.New(true)
   196  		cron.AddOnce(ctx, "@every 2s", func(ctx context.Context) {
   197  			array.Append(1)
   198  		})
   199  		t.Assert(cron.Size(), 1)
   200  		time.Sleep(3000 * time.Millisecond)
   201  		t.Assert(array.Len(), 1)
   202  		t.Assert(cron.Size(), 0)
   203  	})
   204  }
   205  
   206  func TestCron_AddTimes(t *testing.T) {
   207  	gtest.C(t, func(t *gtest.T) {
   208  		cron := gcron.New()
   209  		array := garray.New(true)
   210  		_, _ = cron.AddTimes(ctx, "* * * * * *", 2, func(ctx context.Context) {
   211  			array.Append(1)
   212  		})
   213  		time.Sleep(3500 * time.Millisecond)
   214  		t.Assert(array.Len(), 2)
   215  		t.Assert(cron.Size(), 0)
   216  	})
   217  }
   218  
   219  func TestCron_DelayAdd(t *testing.T) {
   220  	gtest.C(t, func(t *gtest.T) {
   221  		cron := gcron.New()
   222  		array := garray.New(true)
   223  		cron.DelayAdd(ctx, 500*time.Millisecond, "* * * * * *", func(ctx context.Context) {
   224  			array.Append(1)
   225  		})
   226  		t.Assert(cron.Size(), 0)
   227  		time.Sleep(800 * time.Millisecond)
   228  		t.Assert(array.Len(), 0)
   229  		t.Assert(cron.Size(), 1)
   230  		time.Sleep(1000 * time.Millisecond)
   231  		t.Assert(array.Len(), 1)
   232  		t.Assert(cron.Size(), 1)
   233  	})
   234  }
   235  
   236  func TestCron_DelayAddSingleton(t *testing.T) {
   237  	gtest.C(t, func(t *gtest.T) {
   238  		cron := gcron.New()
   239  		array := garray.New(true)
   240  		cron.DelayAddSingleton(ctx, 500*time.Millisecond, "* * * * * *", func(ctx context.Context) {
   241  			array.Append(1)
   242  			time.Sleep(10 * time.Second)
   243  		})
   244  		t.Assert(cron.Size(), 0)
   245  		time.Sleep(2200 * time.Millisecond)
   246  		t.Assert(array.Len(), 1)
   247  		t.Assert(cron.Size(), 1)
   248  	})
   249  }
   250  
   251  func TestCron_DelayAddOnce(t *testing.T) {
   252  	gtest.C(t, func(t *gtest.T) {
   253  		cron := gcron.New()
   254  		array := garray.New(true)
   255  		cron.DelayAddOnce(ctx, 500*time.Millisecond, "* * * * * *", func(ctx context.Context) {
   256  			array.Append(1)
   257  		})
   258  		t.Assert(cron.Size(), 0)
   259  		time.Sleep(800 * time.Millisecond)
   260  		t.Assert(array.Len(), 0)
   261  		t.Assert(cron.Size(), 1)
   262  		time.Sleep(2200 * time.Millisecond)
   263  		t.Assert(array.Len(), 1)
   264  		t.Assert(cron.Size(), 0)
   265  	})
   266  }
   267  
   268  func TestCron_DelayAddTimes(t *testing.T) {
   269  	gtest.C(t, func(t *gtest.T) {
   270  		cron := gcron.New()
   271  		array := garray.New(true)
   272  		cron.DelayAddTimes(ctx, 500*time.Millisecond, "* * * * * *", 2, func(ctx context.Context) {
   273  			array.Append(1)
   274  		})
   275  		t.Assert(cron.Size(), 0)
   276  		time.Sleep(800 * time.Millisecond)
   277  		t.Assert(array.Len(), 0)
   278  		t.Assert(cron.Size(), 1)
   279  		time.Sleep(3000 * time.Millisecond)
   280  		t.Assert(array.Len(), 2)
   281  		t.Assert(cron.Size(), 0)
   282  	})
   283  }
   284  
   285  func TestCron_JobWaiter(t *testing.T) {
   286  	gtest.C(t, func(t *gtest.T) {
   287  		var err error
   288  		s1 := garray.New(true)
   289  		s2 := garray.New(true)
   290  		_, err = gcron.Add(ctx, "* * * * * *", func(ctx context.Context) {
   291  			g.Log().Debug(ctx, "Every second")
   292  			s1.Append(struct{}{})
   293  		}, "MyFirstCronJob")
   294  		t.Assert(err, nil)
   295  		_, err = gcron.Add(ctx, "*/2 * * * * *", func(ctx context.Context) {
   296  			g.Log().Debug(ctx, "Every 2s job start")
   297  			time.Sleep(3 * time.Second)
   298  			s2.Append(struct{}{})
   299  			g.Log().Debug(ctx, "Every 2s job after 3 second end")
   300  		}, "MySecondCronJob")
   301  		t.Assert(err, nil)
   302  
   303  		quit := make(chan os.Signal, 1)
   304  		signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
   305  
   306  		go func() {
   307  			time.Sleep(4 * time.Second) // Ensure that the job is triggered twice
   308  			glog.Print(ctx, "Sending SIGINT")
   309  			quit <- syscall.SIGINT // Send SIGINT
   310  		}()
   311  
   312  		sig := <-quit
   313  		glog.Printf(ctx, "Signal received: %s, stopping cron", sig)
   314  
   315  		glog.Print(ctx, "Waiting for all cron jobs to complete...")
   316  		gcron.StopGracefully()
   317  		glog.Print(ctx, "All cron jobs completed")
   318  		t.Assert(s1.Len(), 4)
   319  		t.Assert(s2.Len(), 2)
   320  	})
   321  }