...

Source file src/github.com/chaos-mesh/chaos-mesh/pkg/scheduler/scheduler_test.go

Documentation: github.com/chaos-mesh/chaos-mesh/pkg/scheduler

     1  // Copyright 2021 Chaos Mesh Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package scheduler
    15  
    16  import (
    17  	"strings"
    18  	"testing"
    19  	"time"
    20  
    21  	"github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
    22  )
    23  
    24  // Modified from the original `TestNext` function in robfig/cron at Dec 15, 2020
    25  func TestLast(t *testing.T) {
    26  	runs := []struct {
    27  		time, spec string
    28  		expected   string
    29  	}{
    30  		// `@every` cron
    31  		{"Jul 9 14:45:00 2012", "@every 1s", "Jul 9 14:45:00 2012"},
    32  		{"Jul 9 14:45:00 2012", "@every 1m", "Jul 9 14:45:00 2012"},
    33  		{"Jul 9 14:45:00 2012", "@every 1h", "Jul 9 14:45:00 2012"},
    34  		{"Jul 9 14:45:00 2012", "@every 1h1m1s", "Jul 9 14:45:00 2012"},
    35  
    36  		// Simple cases
    37  		{"Jul 9 14:45 2012", "0/15 * * * *", "Jul 9 14:45 2012"},
    38  		{"Jul 9 14:59 2012", "0/15 * * * *", "Jul 9 14:45 2012"},
    39  		{"Jul 9 14:59:59 2012", "0/15 * * * *", "Jul 9 14:45 2012"},
    40  
    41  		// Wrap around hours
    42  		{"Jul 9 16:15 2012", "20-35/15 * * * *", "Jul 9 15:35 2012"},
    43  
    44  		// Wrap around days
    45  		{"Jul 9 00:15 2012", "20-35/15 * * * *", "Jul 8 23:35 2012"},
    46  
    47  		// Wrap around months
    48  		{"Jul 9 23:35 2012", "0 0 10 Apr-Oct ?", "Jun 10 00:00 2012"},
    49  		{"Jul 9 23:35 2012", "0 0 */5 Apr,Aug,Oct Mon", "Apr 30 00:00 2012"},
    50  		{"Jul 9 23:35 2012", "0 0 */5 Oct Mon", "Oct 31 00:00 2011"},
    51  
    52  		// Wrap around years
    53  		{"Jan 9 23:35 2012", "0 0 * Feb Mon", "Feb 28 00:00 2011"},
    54  		{"Jan 9 23:35 2012", "0 0 * Feb Mon/2", "Feb 28 00:00 2011"},
    55  
    56  		// Leap year
    57  		{"Jan 9 23:35 2012", "0 0 29 Feb ?", "Feb 29 00:00 2008"},
    58  
    59  		// Daylight savings time 2am EST (-5) -> 3am EDT (-4)
    60  		{"2012-03-11T03:59:00-0400", "TZ=America/New_York 30 1 11 Mar ?", "2012-03-11T02:30:00-0400"},
    61  
    62  		// hourly job
    63  		{"2012-03-11T00:59:00-0500", "TZ=America/New_York 0 * * * ?", "2012-03-11T00:00:00-0500"},
    64  		{"2012-03-11T02:59:00-0400", "TZ=America/New_York 0 * * * ?", "2012-03-11T01:00:00-0500"},
    65  		{"2012-03-11T03:59:00-0400", "TZ=America/New_York 0 * * * ?", "2012-03-11T03:00:00-0400"},
    66  		{"2012-03-11T04:59:00-0400", "TZ=America/New_York 0 * * * ?", "2012-03-11T04:00:00-0400"},
    67  
    68  		// hourly job using CRON_TZ
    69  		{"2012-03-11T00:59:00-0500", "CRON_TZ=America/New_York 0 * * * ?", "2012-03-11T00:00:00-0500"},
    70  		{"2012-03-11T02:59:00-0400", "CRON_TZ=America/New_York 0 * * * ?", "2012-03-11T01:00:00-0500"},
    71  		{"2012-03-11T03:59:00-0400", "CRON_TZ=America/New_York 0 * * * ?", "2012-03-11T03:00:00-0400"},
    72  		{"2012-03-11T04:59:00-0400", "CRON_TZ=America/New_York 0 * * * ?", "2012-03-11T04:00:00-0400"},
    73  
    74  		// 1am nightly job
    75  		{"2012-03-11T01:59:00-0500", "TZ=America/New_York 0 1 * * ?", "2012-03-11T01:00:00-0500"},
    76  		{"2012-03-11T03:00:00-0400", "TZ=America/New_York 0 1 * * ?", "2012-03-11T01:00:00-0500"},
    77  
    78  		// 2am nightly job (skipped)
    79  		{"2012-03-12T01:00:00-0400", "TZ=America/New_York 0 2 * * ?", "2012-03-10T02:00:00-0500"},
    80  
    81  		// Daylight savings time 2am EDT (-4) => 1am EST (-5)
    82  		{"2012-11-04T02:30:00-0500", "TZ=America/New_York 0 0 04 Nov ?", "2012-11-04T00:00:00-0400"},
    83  		{"2012-11-04T01:30:00-0500", "TZ=America/New_York 45 1 04 Nov ?", "2012-11-04T01:45:00-0400"},
    84  
    85  		// hourly job
    86  		{"2012-11-04T00:59:00-0400", "TZ=America/New_York 0 * * * ?", "2012-11-04T00:00:00-0400"},
    87  		{"2012-11-04T01:00:00-0500", "TZ=America/New_York 30 * * * ?", "2012-11-04T01:30:00-0400"},
    88  		{"2012-11-04T01:00:00-0500", "TZ=America/New_York 0 * * * ?", "2012-11-04T01:00:00-0500"},
    89  
    90  		// 1am nightly job (runs twice)
    91  		{"2012-11-04T01:59:00-0400", "TZ=America/New_York 0 1 * * ?", "2012-11-04T01:00:00-0400"},
    92  		{"2012-11-04T02:00:00-0400", "TZ=America/New_York 0 1 * * ?", "2012-11-04T01:00:00-0500"},
    93  		{"2012-11-04T01:00:00-0500", "TZ=America/New_York 0 1 * * ?", "2012-11-04T01:00:00-0500"},
    94  
    95  		// 2am nightly job
    96  		{"2012-11-04T01:59:00-0500", "TZ=America/New_York 0 2 * * ?", "2012-11-03T02:00:00-0400"},
    97  
    98  		// Unsatisfiable
    99  		{"Jul 9 23:35 2012", "0 0 30 Feb ?", ""},
   100  		{"Jul 9 23:35 2012", "0 0 31 Apr ?", ""},
   101  	}
   102  
   103  	for _, c := range runs {
   104  		ss := v1alpha1.SchedulerSpec{Cron: c.spec}
   105  		actual, err := LastTime(ss, getTime(c.time))
   106  		if err != nil {
   107  			t.Error(err)
   108  			continue
   109  		}
   110  		expected := getTime(c.expected)
   111  		if !actual.Equal(expected) {
   112  			t.Errorf("%s, \"%s\": (expected) %v != %v (actual)", c.time, c.spec, expected, actual)
   113  		}
   114  	}
   115  }
   116  
   117  func getTime(value string) time.Time {
   118  	if value == "" {
   119  		return time.Time{}
   120  	}
   121  
   122  	var location = time.Local
   123  	if strings.HasPrefix(value, "TZ=") {
   124  		parts := strings.Fields(value)
   125  		loc, err := time.LoadLocation(parts[0][len("TZ="):])
   126  		if err != nil {
   127  			panic("could not parse location:" + err.Error())
   128  		}
   129  		location = loc
   130  		value = parts[1]
   131  	}
   132  
   133  	var layouts = []string{
   134  		"Jan 2 15:04 2006",
   135  		"Jan 2 15:04:05 2006",
   136  	}
   137  	for _, layout := range layouts {
   138  		if t, err := time.ParseInLocation(layout, value, location); err == nil {
   139  			return t
   140  		}
   141  	}
   142  	if t, err := time.ParseInLocation("2006-01-02T15:04:05-0700", value, location); err == nil {
   143  		return t
   144  	}
   145  	panic("could not parse time value " + value)
   146  }
   147