github.com/rohankumardubey/proxyfs@v0.0.0-20210108201508-653efa9ab00e/inode/cron_test.go (about)

     1  package inode
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/swiftstack/ProxyFS/conf"
     8  )
     9  
    10  func TestLoadSnapShotPolicy(t *testing.T) {
    11  	var (
    12  		err                error
    13  		testConfMap        conf.ConfMap
    14  		testConfMapStrings []string
    15  		volume             *volumeStruct
    16  	)
    17  
    18  	// Case 1 - no SnapShotPolicy
    19  
    20  	testConfMapStrings = []string{}
    21  
    22  	testConfMap, err = conf.MakeConfMapFromStrings(testConfMapStrings)
    23  	if nil != err {
    24  		t.Fatalf("Case 1: conf.MakeConfMapFromStrings() failed: %v", err)
    25  	}
    26  
    27  	volume = &volumeStruct{volumeName: "TestVolume", snapShotPolicy: nil}
    28  
    29  	err = volume.loadSnapShotPolicy(testConfMap)
    30  	if nil != err {
    31  		t.Fatalf("Case 1: loadSnapShotPolicy() failed: %v", err)
    32  	}
    33  
    34  	if nil != volume.snapShotPolicy {
    35  		t.Fatalf("Case 1: loadSnapShotPolicy() returned non-nil snapShotPolicy")
    36  	}
    37  
    38  	// Case 2 - SnapShotPolicy with empty ScheduleList and no TimeZone
    39  
    40  	testConfMapStrings = []string{
    41  		"SnapShotPolicy:CommonSnapShotPolicy.ScheduleList=",
    42  		"Volume:TestVolume.SnapShotPolicy=CommonSnapShotPolicy",
    43  	}
    44  
    45  	testConfMap, err = conf.MakeConfMapFromStrings(testConfMapStrings)
    46  	if nil != err {
    47  		t.Fatalf("Case 2: conf.MakeConfMapFromStrings() failed: %v", err)
    48  	}
    49  
    50  	volume = &volumeStruct{volumeName: "TestVolume", snapShotPolicy: nil}
    51  
    52  	err = volume.loadSnapShotPolicy(testConfMap)
    53  	if nil != err {
    54  		t.Fatalf("Case 2: loadSnapShotPolicy() failed: %v", err)
    55  	}
    56  
    57  	if nil != volume.snapShotPolicy {
    58  		t.Fatalf("Case 2: loadSnapShotPolicy() returned non-nil snapShotPolicy")
    59  	}
    60  
    61  	// Case 3 - SnapShotPolicy with trivial ScheduleList and no TimeZone
    62  
    63  	testConfMapStrings = []string{
    64  		"SnapShotSchedule:MinutelySnapShotSchedule.CronTab=* * * * *", // ==> snapShotPolicy.schedule[0]
    65  		"SnapShotSchedule:MinutelySnapShotSchedule.Keep=59",
    66  		"SnapShotPolicy:CommonSnapShotPolicy.ScheduleList=MinutelySnapShotSchedule",
    67  		"Volume:TestVolume.SnapShotPolicy=CommonSnapShotPolicy",
    68  	}
    69  
    70  	testConfMap, err = conf.MakeConfMapFromStrings(testConfMapStrings)
    71  	if nil != err {
    72  		t.Fatalf("Case 3: conf.MakeConfMapFromStrings() failed: %v", err)
    73  	}
    74  
    75  	volume = &volumeStruct{volumeName: "TestVolume", snapShotPolicy: nil}
    76  
    77  	err = volume.loadSnapShotPolicy(testConfMap)
    78  	if nil != err {
    79  		t.Fatalf("Case 3: loadSnapShotPolicy() failed: %v", err)
    80  	}
    81  
    82  	if "CommonSnapShotPolicy" != volume.snapShotPolicy.name {
    83  		t.Fatalf("Case 3: loadSnapShotPolicy() returned snapShotPolicy with unexpected .name")
    84  	}
    85  	if 1 != len(volume.snapShotPolicy.schedule) {
    86  		t.Fatalf("Case 3: loadSnapShotPolicy() returned snapShotPolicy with unexpected .schedule")
    87  	}
    88  	if "MinutelySnapShotSchedule" != volume.snapShotPolicy.schedule[0].name {
    89  		t.Fatalf("Case 3: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .name")
    90  	}
    91  	if volume.snapShotPolicy.schedule[0].minuteSpecified {
    92  		t.Fatalf("Case 3: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .minuteSpecified")
    93  	}
    94  	if volume.snapShotPolicy.schedule[0].hourSpecified {
    95  		t.Fatalf("Case 3: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .hourSpecified")
    96  	}
    97  	if volume.snapShotPolicy.schedule[0].dayOfMonthSpecified {
    98  		t.Fatalf("Case 3: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .dayOfMonthSpecified")
    99  	}
   100  	if volume.snapShotPolicy.schedule[0].monthSpecified {
   101  		t.Fatalf("Case 3: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .monthSpecified")
   102  	}
   103  	if volume.snapShotPolicy.schedule[0].dayOfWeekSpecified {
   104  		t.Fatalf("Case 3: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .dayOfWeekSpecified")
   105  	}
   106  	if 59 != volume.snapShotPolicy.schedule[0].keep {
   107  		t.Fatalf("Case 3: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .keep")
   108  	}
   109  	if "UTC" != volume.snapShotPolicy.location.String() {
   110  		t.Fatalf("Case 3: loadSnapShotPolicy() returned snapShotPolicy with unexpected .location")
   111  	}
   112  
   113  	// Case 4 - SnapShotPolicy with trivial ScheduleList and empty TimeZone
   114  
   115  	testConfMapStrings = []string{
   116  		"SnapShotSchedule:MinutelySnapShotSchedule.CronTab=* * * * *", // ==> snapShotPolicy.schedule[0]
   117  		"SnapShotSchedule:MinutelySnapShotSchedule.Keep=59",
   118  		"SnapShotPolicy:CommonSnapShotPolicy.ScheduleList=MinutelySnapShotSchedule",
   119  		"SnapShotPolicy:CommonSnapShotPolicy.TimeZone=",
   120  		"Volume:TestVolume.SnapShotPolicy=CommonSnapShotPolicy",
   121  	}
   122  
   123  	testConfMap, err = conf.MakeConfMapFromStrings(testConfMapStrings)
   124  	if nil != err {
   125  		t.Fatalf("Case 4: conf.MakeConfMapFromStrings() failed: %v", err)
   126  	}
   127  
   128  	volume = &volumeStruct{volumeName: "TestVolume", snapShotPolicy: nil}
   129  
   130  	err = volume.loadSnapShotPolicy(testConfMap)
   131  	if nil != err {
   132  		t.Fatalf("Case 4: loadSnapShotPolicy() failed: %v", err)
   133  	}
   134  
   135  	if "CommonSnapShotPolicy" != volume.snapShotPolicy.name {
   136  		t.Fatalf("Case 4: loadSnapShotPolicy() returned snapShotPolicy with unexpected .name")
   137  	}
   138  	if 1 != len(volume.snapShotPolicy.schedule) {
   139  		t.Fatalf("Case 4: loadSnapShotPolicy() returned snapShotPolicy with unexpected .schedule")
   140  	}
   141  	if "MinutelySnapShotSchedule" != volume.snapShotPolicy.schedule[0].name {
   142  		t.Fatalf("Case 4: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .name")
   143  	}
   144  	if volume.snapShotPolicy.schedule[0].minuteSpecified {
   145  		t.Fatalf("Case 4: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .minuteSpecified")
   146  	}
   147  	if volume.snapShotPolicy.schedule[0].hourSpecified {
   148  		t.Fatalf("Case 4: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .hourSpecified")
   149  	}
   150  	if volume.snapShotPolicy.schedule[0].dayOfMonthSpecified {
   151  		t.Fatalf("Case 4: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .dayOfMonthSpecified")
   152  	}
   153  	if volume.snapShotPolicy.schedule[0].monthSpecified {
   154  		t.Fatalf("Case 4: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .monthSpecified")
   155  	}
   156  	if volume.snapShotPolicy.schedule[0].dayOfWeekSpecified {
   157  		t.Fatalf("Case 4: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .dayOfWeekSpecified")
   158  	}
   159  	if 59 != volume.snapShotPolicy.schedule[0].keep {
   160  		t.Fatalf("Case 4: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .keep")
   161  	}
   162  	if "UTC" != volume.snapShotPolicy.location.String() {
   163  		t.Fatalf("Case 4: loadSnapShotPolicy() returned snapShotPolicy with unexpected .location")
   164  	}
   165  
   166  	// Case 5 - SnapShotPolicy with trivial ScheduleList and TimeZone of "UTC"
   167  
   168  	testConfMapStrings = []string{
   169  		"SnapShotSchedule:MinutelySnapShotSchedule.CronTab=* * * * *", // ==> snapShotPolicy.schedule[0]
   170  		"SnapShotSchedule:MinutelySnapShotSchedule.Keep=59",
   171  		"SnapShotPolicy:CommonSnapShotPolicy.ScheduleList=MinutelySnapShotSchedule",
   172  		"SnapShotPolicy:CommonSnapShotPolicy.TimeZone=UTC",
   173  		"Volume:TestVolume.SnapShotPolicy=CommonSnapShotPolicy",
   174  	}
   175  
   176  	testConfMap, err = conf.MakeConfMapFromStrings(testConfMapStrings)
   177  	if nil != err {
   178  		t.Fatalf("Case 5: conf.MakeConfMapFromStrings() failed: %v", err)
   179  	}
   180  
   181  	volume = &volumeStruct{volumeName: "TestVolume", snapShotPolicy: nil}
   182  
   183  	err = volume.loadSnapShotPolicy(testConfMap)
   184  	if nil != err {
   185  		t.Fatalf("Case 5: loadSnapShotPolicy() failed: %v", err)
   186  	}
   187  
   188  	if "CommonSnapShotPolicy" != volume.snapShotPolicy.name {
   189  		t.Fatalf("Case 5: loadSnapShotPolicy() returned snapShotPolicy with unexpected .name")
   190  	}
   191  	if 1 != len(volume.snapShotPolicy.schedule) {
   192  		t.Fatalf("Case 5: loadSnapShotPolicy() returned snapShotPolicy with unexpected .schedule")
   193  	}
   194  	if "MinutelySnapShotSchedule" != volume.snapShotPolicy.schedule[0].name {
   195  		t.Fatalf("Case 5: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .name")
   196  	}
   197  	if volume.snapShotPolicy.schedule[0].minuteSpecified {
   198  		t.Fatalf("Case 5: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .minuteSpecified")
   199  	}
   200  	if volume.snapShotPolicy.schedule[0].hourSpecified {
   201  		t.Fatalf("Case 5: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .hourSpecified")
   202  	}
   203  	if volume.snapShotPolicy.schedule[0].dayOfMonthSpecified {
   204  		t.Fatalf("Case 5: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .dayOfMonthSpecified")
   205  	}
   206  	if volume.snapShotPolicy.schedule[0].monthSpecified {
   207  		t.Fatalf("Case 5: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .monthSpecified")
   208  	}
   209  	if volume.snapShotPolicy.schedule[0].dayOfWeekSpecified {
   210  		t.Fatalf("Case 5: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .dayOfWeekSpecified")
   211  	}
   212  	if 59 != volume.snapShotPolicy.schedule[0].keep {
   213  		t.Fatalf("Case 5: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .keep")
   214  	}
   215  	if "UTC" != volume.snapShotPolicy.location.String() {
   216  		t.Fatalf("Case 5: loadSnapShotPolicy() returned snapShotPolicy with unexpected .location")
   217  	}
   218  
   219  	// Case 6 - SnapShotPolicy with trivial ScheduleList and TimeZone of "Local"
   220  
   221  	testConfMapStrings = []string{
   222  		"SnapShotSchedule:MinutelySnapShotSchedule.CronTab=* * * * *", // ==> snapShotPolicy.schedule[0]
   223  		"SnapShotSchedule:MinutelySnapShotSchedule.Keep=59",
   224  		"SnapShotPolicy:CommonSnapShotPolicy.ScheduleList=MinutelySnapShotSchedule",
   225  		"SnapShotPolicy:CommonSnapShotPolicy.TimeZone=Local",
   226  		"Volume:TestVolume.SnapShotPolicy=CommonSnapShotPolicy",
   227  	}
   228  
   229  	testConfMap, err = conf.MakeConfMapFromStrings(testConfMapStrings)
   230  	if nil != err {
   231  		t.Fatalf("Case 6: conf.MakeConfMapFromStrings() failed: %v", err)
   232  	}
   233  
   234  	volume = &volumeStruct{volumeName: "TestVolume", snapShotPolicy: nil}
   235  
   236  	err = volume.loadSnapShotPolicy(testConfMap)
   237  	if nil != err {
   238  		t.Fatalf("Case 6: loadSnapShotPolicy() failed: %v", err)
   239  	}
   240  
   241  	if "CommonSnapShotPolicy" != volume.snapShotPolicy.name {
   242  		t.Fatalf("Case 6: loadSnapShotPolicy() returned snapShotPolicy with unexpected .name")
   243  	}
   244  	if 1 != len(volume.snapShotPolicy.schedule) {
   245  		t.Fatalf("Case 6: loadSnapShotPolicy() returned snapShotPolicy with unexpected .schedule")
   246  	}
   247  	if "MinutelySnapShotSchedule" != volume.snapShotPolicy.schedule[0].name {
   248  		t.Fatalf("Case 6: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .name")
   249  	}
   250  	if volume.snapShotPolicy.schedule[0].minuteSpecified {
   251  		t.Fatalf("Case 6: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .minuteSpecified")
   252  	}
   253  	if volume.snapShotPolicy.schedule[0].hourSpecified {
   254  		t.Fatalf("Case 6: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .hourSpecified")
   255  	}
   256  	if volume.snapShotPolicy.schedule[0].dayOfMonthSpecified {
   257  		t.Fatalf("Case 6: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .dayOfMonthSpecified")
   258  	}
   259  	if volume.snapShotPolicy.schedule[0].monthSpecified {
   260  		t.Fatalf("Case 6: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .monthSpecified")
   261  	}
   262  	if volume.snapShotPolicy.schedule[0].dayOfWeekSpecified {
   263  		t.Fatalf("Case 6: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .dayOfWeekSpecified")
   264  	}
   265  	if 59 != volume.snapShotPolicy.schedule[0].keep {
   266  		t.Fatalf("Case 6: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .keep")
   267  	}
   268  	if "Local" != volume.snapShotPolicy.location.String() {
   269  		t.Fatalf("Case 6: loadSnapShotPolicy() returned snapShotPolicy with unexpected .location")
   270  	}
   271  
   272  	// Case 7 - SnapShotPolicy with exhaustive ScheduleList and a specific TimeZone
   273  
   274  	testConfMapStrings = []string{
   275  		"SnapShotSchedule:MinutelySnapShotSchedule.CronTab=* * * * *", // ==> snapShotPolicy.schedule[0]
   276  		"SnapShotSchedule:MinutelySnapShotSchedule.Keep=59",
   277  		"SnapShotSchedule:HourlySnapShotSchedule.CronTab=0 * * * *", //   ==> snapShotPolicy.schedule[1]
   278  		"SnapShotSchedule:HourlySnapShotSchedule.Keep=23",
   279  		"SnapShotSchedule:DailySnapShotSchedule.CronTab=0 0 * * *", //    ==> snapShotPolicy.schedule[2]
   280  		"SnapShotSchedule:DailySnapShotSchedule.Keep=6",
   281  		"SnapShotSchedule:WeeklySnapShotSchedule.CronTab=0 0 * * 0", //   ==> snapShotPolicy.schedule[3]
   282  		"SnapShotSchedule:WeeklySnapShotSchedule.Keep=8",
   283  		"SnapShotSchedule:MonthlySnapShotSchedule.CronTab=0 0 1 * *", //  ==> snapShotPolicy.schedule[4]
   284  		"SnapShotSchedule:MonthlySnapShotSchedule.Keep=11",
   285  		"SnapShotSchedule:YearlySnapShotSchedule.CronTab=0 0 1 1 *", //   ==> snapShotPolicy.schedule[5]
   286  		"SnapShotSchedule:YearlySnapShotSchedule.Keep=4",
   287  		"SnapShotPolicy:CommonSnapShotPolicy.ScheduleList=MinutelySnapShotSchedule,HourlySnapShotSchedule,DailySnapShotSchedule,WeeklySnapShotSchedule,MonthlySnapShotSchedule,YearlySnapShotSchedule",
   288  		"SnapShotPolicy:CommonSnapShotPolicy.TimeZone=America/Los_Angeles",
   289  		"Volume:TestVolume.SnapShotPolicy=CommonSnapShotPolicy",
   290  	}
   291  
   292  	testConfMap, err = conf.MakeConfMapFromStrings(testConfMapStrings)
   293  	if nil != err {
   294  		t.Fatalf("Case 7: conf.MakeConfMapFromStrings() failed: %v", err)
   295  	}
   296  
   297  	volume = &volumeStruct{volumeName: "TestVolume", snapShotPolicy: nil}
   298  
   299  	err = volume.loadSnapShotPolicy(testConfMap)
   300  	if nil != err {
   301  		t.Fatalf("Case 7: loadSnapShotPolicy() failed: %v", err)
   302  	}
   303  
   304  	if "CommonSnapShotPolicy" != volume.snapShotPolicy.name {
   305  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy with unexpected .name")
   306  	}
   307  
   308  	if 6 != len(volume.snapShotPolicy.schedule) {
   309  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy with unexpected .schedule")
   310  	}
   311  
   312  	if "MinutelySnapShotSchedule" != volume.snapShotPolicy.schedule[0].name {
   313  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .name")
   314  	}
   315  	if volume.snapShotPolicy.schedule[0].minuteSpecified {
   316  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .minuteSpecified")
   317  	}
   318  	if volume.snapShotPolicy.schedule[0].hourSpecified {
   319  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .hourSpecified")
   320  	}
   321  	if volume.snapShotPolicy.schedule[0].dayOfMonthSpecified {
   322  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .dayOfMonthSpecified")
   323  	}
   324  	if volume.snapShotPolicy.schedule[0].monthSpecified {
   325  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .monthSpecified")
   326  	}
   327  	if volume.snapShotPolicy.schedule[0].dayOfWeekSpecified {
   328  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .dayOfWeekSpecified")
   329  	}
   330  	if 59 != volume.snapShotPolicy.schedule[0].keep {
   331  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[0] with unexpected .keep")
   332  	}
   333  
   334  	if "HourlySnapShotSchedule" != volume.snapShotPolicy.schedule[1].name {
   335  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[1] with unexpected .name")
   336  	}
   337  	if !volume.snapShotPolicy.schedule[1].minuteSpecified {
   338  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[1] with unexpected .minuteSpecified")
   339  	}
   340  	if 0 != volume.snapShotPolicy.schedule[1].minute {
   341  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[1] with unexpected .minute")
   342  	}
   343  	if volume.snapShotPolicy.schedule[1].hourSpecified {
   344  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[1] with unexpected .hourSpecified")
   345  	}
   346  	if volume.snapShotPolicy.schedule[1].dayOfMonthSpecified {
   347  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[1] with unexpected .dayOfMonthSpecified")
   348  	}
   349  	if volume.snapShotPolicy.schedule[1].monthSpecified {
   350  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[1] with unexpected .monthSpecified")
   351  	}
   352  	if volume.snapShotPolicy.schedule[1].dayOfWeekSpecified {
   353  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[1] with unexpected .dayOfWeekSpecified")
   354  	}
   355  	if 23 != volume.snapShotPolicy.schedule[1].keep {
   356  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[1] with unexpected .keep")
   357  	}
   358  
   359  	if "DailySnapShotSchedule" != volume.snapShotPolicy.schedule[2].name {
   360  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[2] with unexpected .name")
   361  	}
   362  	if !volume.snapShotPolicy.schedule[2].minuteSpecified {
   363  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[2] with unexpected .minuteSpecified")
   364  	}
   365  	if 0 != volume.snapShotPolicy.schedule[2].minute {
   366  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[2] with unexpected .minute")
   367  	}
   368  	if !volume.snapShotPolicy.schedule[2].hourSpecified {
   369  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[2] with unexpected .hourSpecified")
   370  	}
   371  	if 0 != volume.snapShotPolicy.schedule[2].hour {
   372  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[2] with unexpected .hour")
   373  	}
   374  	if volume.snapShotPolicy.schedule[2].dayOfMonthSpecified {
   375  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[2] with unexpected .dayOfMonthSpecified")
   376  	}
   377  	if volume.snapShotPolicy.schedule[2].monthSpecified {
   378  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[2] with unexpected .monthSpecified")
   379  	}
   380  	if volume.snapShotPolicy.schedule[2].dayOfWeekSpecified {
   381  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[2] with unexpected .dayOfWeekSpecified")
   382  	}
   383  	if 6 != volume.snapShotPolicy.schedule[2].keep {
   384  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[2] with unexpected .keep")
   385  	}
   386  
   387  	if "WeeklySnapShotSchedule" != volume.snapShotPolicy.schedule[3].name {
   388  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[3] with unexpected .name")
   389  	}
   390  	if !volume.snapShotPolicy.schedule[3].minuteSpecified {
   391  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[3] with unexpected .minuteSpecified")
   392  	}
   393  	if 0 != volume.snapShotPolicy.schedule[3].minute {
   394  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[3] with unexpected .minute")
   395  	}
   396  	if !volume.snapShotPolicy.schedule[3].hourSpecified {
   397  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[3] with unexpected .hourSpecified")
   398  	}
   399  	if 0 != volume.snapShotPolicy.schedule[3].hour {
   400  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[3] with unexpected .hour")
   401  	}
   402  	if volume.snapShotPolicy.schedule[3].dayOfMonthSpecified {
   403  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[3] with unexpected .dayOfMonthSpecified")
   404  	}
   405  	if volume.snapShotPolicy.schedule[3].monthSpecified {
   406  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[3] with unexpected .monthSpecified")
   407  	}
   408  	if !volume.snapShotPolicy.schedule[3].dayOfWeekSpecified {
   409  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[3] with unexpected .dayOfWeekSpecified")
   410  	}
   411  	if 0 != volume.snapShotPolicy.schedule[3].dayOfWeek {
   412  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[3] with unexpected .dayOfWeek")
   413  	}
   414  	if 8 != volume.snapShotPolicy.schedule[3].keep {
   415  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[3] with unexpected .keep")
   416  	}
   417  
   418  	if "MonthlySnapShotSchedule" != volume.snapShotPolicy.schedule[4].name {
   419  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[4] with unexpected .name")
   420  	}
   421  	if !volume.snapShotPolicy.schedule[4].minuteSpecified {
   422  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[4] with unexpected .minuteSpecified")
   423  	}
   424  	if 0 != volume.snapShotPolicy.schedule[4].minute {
   425  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[4] with unexpected .minute")
   426  	}
   427  	if !volume.snapShotPolicy.schedule[4].hourSpecified {
   428  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[4] with unexpected .hourSpecified")
   429  	}
   430  	if 0 != volume.snapShotPolicy.schedule[4].hour {
   431  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[4] with unexpected .hour")
   432  	}
   433  	if !volume.snapShotPolicy.schedule[4].dayOfMonthSpecified {
   434  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[4] with unexpected .dayOfMonthSpecified")
   435  	}
   436  	if 1 != volume.snapShotPolicy.schedule[4].dayOfMonth {
   437  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[4] with unexpected .dayOfMonth")
   438  	}
   439  	if volume.snapShotPolicy.schedule[4].monthSpecified {
   440  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[4] with unexpected .monthSpecified")
   441  	}
   442  	if volume.snapShotPolicy.schedule[4].dayOfWeekSpecified {
   443  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[4] with unexpected .dayOfWeekSpecified")
   444  	}
   445  	if 11 != volume.snapShotPolicy.schedule[4].keep {
   446  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[4] with unexpected .keep")
   447  	}
   448  
   449  	if "YearlySnapShotSchedule" != volume.snapShotPolicy.schedule[5].name {
   450  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[5] with unexpected .name")
   451  	}
   452  	if !volume.snapShotPolicy.schedule[5].minuteSpecified {
   453  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[5] with unexpected .minuteSpecified")
   454  	}
   455  	if 0 != volume.snapShotPolicy.schedule[5].minute {
   456  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[5] with unexpected .minute")
   457  	}
   458  	if !volume.snapShotPolicy.schedule[5].hourSpecified {
   459  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[5] with unexpected .hourSpecified")
   460  	}
   461  	if 0 != volume.snapShotPolicy.schedule[5].hour {
   462  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[5] with unexpected .hour")
   463  	}
   464  	if !volume.snapShotPolicy.schedule[5].dayOfMonthSpecified {
   465  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[5] with unexpected .dayOfMonthSpecified")
   466  	}
   467  	if 1 != volume.snapShotPolicy.schedule[5].dayOfMonth {
   468  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[5] with unexpected .dayOfMonth")
   469  	}
   470  	if !volume.snapShotPolicy.schedule[5].monthSpecified {
   471  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[5] with unexpected .monthSpecified")
   472  	}
   473  	if 1 != volume.snapShotPolicy.schedule[5].month {
   474  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[5] with unexpected .month")
   475  	}
   476  	if volume.snapShotPolicy.schedule[5].dayOfWeekSpecified {
   477  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[5] with unexpected .dayOfWeekSpecified")
   478  	}
   479  	if 4 != volume.snapShotPolicy.schedule[5].keep {
   480  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy.schedule[5] with unexpected .keep")
   481  	}
   482  
   483  	if "America/Los_Angeles" != volume.snapShotPolicy.location.String() {
   484  		t.Fatalf("Case 7: loadSnapShotPolicy() returned snapShotPolicy with unexpected .location")
   485  	}
   486  }
   487  
   488  func TestSnapShotScheduleCompare(t *testing.T) {
   489  	var (
   490  		err                error
   491  		matches            bool
   492  		matchingTime       time.Time
   493  		mismatchingTime    time.Time
   494  		testConfMap        conf.ConfMap
   495  		testConfMapStrings []string
   496  		volume             *volumeStruct
   497  	)
   498  
   499  	testConfMapStrings = []string{
   500  		"SnapShotSchedule:MinutelySnapShotSchedule.CronTab=* * * * *", // ==> snapShotPolicy.schedule[0]
   501  		"SnapShotSchedule:MinutelySnapShotSchedule.Keep=59",
   502  		"SnapShotSchedule:HourlySnapShotSchedule.CronTab=0 * * * *", //   ==> snapShotPolicy.schedule[1]
   503  		"SnapShotSchedule:HourlySnapShotSchedule.Keep=23",
   504  		"SnapShotSchedule:DailySnapShotSchedule.CronTab=0 0 * * *", //    ==> snapShotPolicy.schedule[2]
   505  		"SnapShotSchedule:DailySnapShotSchedule.Keep=6",
   506  		"SnapShotSchedule:WeeklySnapShotSchedule.CronTab=0 0 * * 0", //   ==> snapShotPolicy.schedule[3]
   507  		"SnapShotSchedule:WeeklySnapShotSchedule.Keep=8",
   508  		"SnapShotSchedule:MonthlySnapShotSchedule.CronTab=0 0 1 * *", //  ==> snapShotPolicy.schedule[4]
   509  		"SnapShotSchedule:MonthlySnapShotSchedule.Keep=11",
   510  		"SnapShotSchedule:YearlySnapShotSchedule.CronTab=0 0 1 1 *", //   ==> snapShotPolicy.schedule[5]
   511  		"SnapShotSchedule:YearlySnapShotSchedule.Keep=4",
   512  		"SnapShotPolicy:CommonSnapShotPolicy.ScheduleList=MinutelySnapShotSchedule,HourlySnapShotSchedule,DailySnapShotSchedule,WeeklySnapShotSchedule,MonthlySnapShotSchedule,YearlySnapShotSchedule",
   513  		"SnapShotPolicy:CommonSnapShotPolicy.TimeZone=America/Los_Angeles",
   514  		"Volume:TestVolume.SnapShotPolicy=CommonSnapShotPolicy",
   515  	}
   516  
   517  	testConfMap, err = conf.MakeConfMapFromStrings(testConfMapStrings)
   518  	if nil != err {
   519  		t.Fatalf("conf.MakeConfMapFromStrings() failed: %v", err)
   520  	}
   521  
   522  	volume = &volumeStruct{volumeName: "TestVolume", snapShotPolicy: nil}
   523  
   524  	err = volume.loadSnapShotPolicy(testConfMap)
   525  	if nil != err {
   526  		t.Fatalf("loadSnapShotPolicy() failed: %v", err)
   527  	}
   528  
   529  	matchingTime = time.Date(2017, time.January, 1, 0, 0, 0, 0, volume.snapShotPolicy.location) // A Sunday
   530  
   531  	mismatchingTime = time.Date(2017, time.January, 1, 0, 0, 1, 0, volume.snapShotPolicy.location) // +1 second
   532  	matches = volume.snapShotPolicy.schedule[0].compare(matchingTime)
   533  	if !matches {
   534  		t.Fatalf("snapShotPolicy.schedule[0].compare(matchingTime) should have returned true")
   535  	}
   536  	matches = volume.snapShotPolicy.schedule[0].compare(mismatchingTime)
   537  	if matches {
   538  		t.Fatalf("snapShotPolicy.schedule[0].compare(mismatchingTime) should have returned false")
   539  	}
   540  
   541  	mismatchingTime = time.Date(2017, time.January, 1, 0, 1, 0, 0, volume.snapShotPolicy.location) // +1 minute
   542  	matches = volume.snapShotPolicy.schedule[1].compare(matchingTime)
   543  	if !matches {
   544  		t.Fatalf("snapShotPolicy.schedule[1].compare(matchingTime) should have returned true")
   545  	}
   546  	matches = volume.snapShotPolicy.schedule[1].compare(mismatchingTime)
   547  	if matches {
   548  		t.Fatalf("snapShotPolicy.schedule[1].compare(mismatchingTime) should have returned false")
   549  	}
   550  
   551  	mismatchingTime = time.Date(2017, time.January, 1, 1, 0, 0, 0, volume.snapShotPolicy.location) // +1 hour
   552  	matches = volume.snapShotPolicy.schedule[2].compare(matchingTime)
   553  	if !matches {
   554  		t.Fatalf("snapShotPolicy.schedule[2].compare(matchingTime) should have returned true")
   555  	}
   556  	matches = volume.snapShotPolicy.schedule[2].compare(mismatchingTime)
   557  	if matches {
   558  		t.Fatalf("snapShotPolicy.schedule[2].compare(mismatchingTime) should have returned false")
   559  	}
   560  
   561  	mismatchingTime = time.Date(2017, time.January, 2, 0, 0, 0, 0, volume.snapShotPolicy.location) // +1 day
   562  	matches = volume.snapShotPolicy.schedule[3].compare(matchingTime)
   563  	if !matches {
   564  		t.Fatalf("snapShotPolicy.schedule[3].compare(matchingTime) should have returned true")
   565  	}
   566  	matches = volume.snapShotPolicy.schedule[3].compare(mismatchingTime)
   567  	if matches {
   568  		t.Fatalf("snapShotPolicy.schedule[3].compare(mismatchingTime) should have returned false")
   569  	}
   570  
   571  	mismatchingTime = time.Date(2017, time.January, 2, 0, 0, 0, 0, volume.snapShotPolicy.location) // A Monday
   572  	matches = volume.snapShotPolicy.schedule[4].compare(matchingTime)
   573  	if !matches {
   574  		t.Fatalf("snapShotPolicy.schedule[4].compare(matchingTime) should have returned true")
   575  	}
   576  	matches = volume.snapShotPolicy.schedule[4].compare(mismatchingTime)
   577  	if matches {
   578  		t.Fatalf("snapShotPolicy.schedule[4].compare(mismatchingTime) should have returned false")
   579  	}
   580  
   581  	mismatchingTime = time.Date(2017, time.February, 1, 0, 0, 0, 0, volume.snapShotPolicy.location) // +1 month
   582  	matches = volume.snapShotPolicy.schedule[5].compare(matchingTime)
   583  	if !matches {
   584  		t.Fatalf("snapShotPolicy.schedule[5].compare(matchingTime) should have returned true")
   585  	}
   586  	matches = volume.snapShotPolicy.schedule[5].compare(mismatchingTime)
   587  	if matches {
   588  		t.Fatalf("snapShotPolicy.schedule[5].compare(mismatchingTime) should have returned false")
   589  	}
   590  }
   591  
   592  func TestSnapShotScheduleNext(t *testing.T) {
   593  	var (
   594  		err                error
   595  		nextTime           time.Time
   596  		testConfMap        conf.ConfMap
   597  		testConfMapStrings []string
   598  		timeNow            time.Time
   599  		volume             *volumeStruct
   600  	)
   601  
   602  	testConfMapStrings = []string{
   603  		"SnapShotSchedule:MinutelySnapShotSchedule.CronTab=* * * * *", // ==> snapShotPolicy.schedule[0]
   604  		"SnapShotSchedule:MinutelySnapShotSchedule.Keep=59",
   605  		"SnapShotSchedule:HourlySnapShotSchedule.CronTab=0 * * * *", //   ==> snapShotPolicy.schedule[1]
   606  		"SnapShotSchedule:HourlySnapShotSchedule.Keep=23",
   607  		"SnapShotSchedule:DailySnapShotSchedule.CronTab=0 0 * * *", //    ==> snapShotPolicy.schedule[2]
   608  		"SnapShotSchedule:DailySnapShotSchedule.Keep=6",
   609  		"SnapShotSchedule:WeeklySnapShotSchedule.CronTab=0 0 * * 0", //   ==> snapShotPolicy.schedule[3]
   610  		"SnapShotSchedule:WeeklySnapShotSchedule.Keep=8",
   611  		"SnapShotSchedule:MonthlySnapShotSchedule.CronTab=0 0 1 * *", //  ==> snapShotPolicy.schedule[4]
   612  		"SnapShotSchedule:MonthlySnapShotSchedule.Keep=11",
   613  		"SnapShotSchedule:YearlySnapShotSchedule.CronTab=0 0 1 1 *", //   ==> snapShotPolicy.schedule[5]
   614  		"SnapShotSchedule:YearlySnapShotSchedule.Keep=4",
   615  		"SnapShotPolicy:CommonSnapShotPolicy.ScheduleList=MinutelySnapShotSchedule,HourlySnapShotSchedule,DailySnapShotSchedule,WeeklySnapShotSchedule,MonthlySnapShotSchedule,YearlySnapShotSchedule",
   616  		"SnapShotPolicy:CommonSnapShotPolicy.TimeZone=America/Los_Angeles",
   617  		"Volume:TestVolume.SnapShotPolicy=CommonSnapShotPolicy",
   618  	}
   619  
   620  	testConfMap, err = conf.MakeConfMapFromStrings(testConfMapStrings)
   621  	if nil != err {
   622  		t.Fatalf("conf.MakeConfMapFromStrings() failed: %v", err)
   623  	}
   624  
   625  	volume = &volumeStruct{volumeName: "TestVolume", snapShotPolicy: nil}
   626  
   627  	err = volume.loadSnapShotPolicy(testConfMap)
   628  	if nil != err {
   629  		t.Fatalf("loadSnapShotPolicy() failed: %v", err)
   630  	}
   631  
   632  	timeNow = time.Date(2017, time.January, 1, 0, 0, 0, 0, volume.snapShotPolicy.location) // A Sunday
   633  
   634  	nextTime = volume.snapShotPolicy.schedule[0].next(timeNow)
   635  	if !nextTime.Equal(time.Date(2017, time.January, 1, 0, 1, 0, 0, volume.snapShotPolicy.location)) {
   636  		t.Fatalf("snapShotPolicy.schedule[0].next(timeNow) returned unexpected time: %v", nextTime)
   637  	}
   638  
   639  	nextTime = volume.snapShotPolicy.schedule[1].next(timeNow)
   640  	if !nextTime.Equal(time.Date(2017, time.January, 1, 1, 0, 0, 0, volume.snapShotPolicy.location)) {
   641  		t.Fatalf("snapShotPolicy.schedule[1].next(timeNow) returned unexpected time: %v", nextTime)
   642  	}
   643  
   644  	nextTime = volume.snapShotPolicy.schedule[2].next(timeNow)
   645  	if !nextTime.Equal(time.Date(2017, time.January, 2, 0, 0, 0, 0, volume.snapShotPolicy.location)) {
   646  		t.Fatalf("snapShotPolicy.schedule[2].next(timeNow) returned unexpected time: %v", nextTime)
   647  	}
   648  
   649  	nextTime = volume.snapShotPolicy.schedule[3].next(timeNow)
   650  	if !nextTime.Equal(time.Date(2017, time.January, 8, 0, 0, 0, 0, volume.snapShotPolicy.location)) {
   651  		t.Fatalf("snapShotPolicy.schedule[3].next(timeNow) returned unexpected time: %v", nextTime)
   652  	}
   653  
   654  	nextTime = volume.snapShotPolicy.schedule[4].next(timeNow)
   655  	if !nextTime.Equal(time.Date(2017, time.February, 1, 0, 0, 0, 0, volume.snapShotPolicy.location)) {
   656  		t.Fatalf("snapShotPolicy.schedule[4].next(timeNow) returned unexpected time: %v", nextTime)
   657  	}
   658  
   659  	nextTime = volume.snapShotPolicy.schedule[5].next(timeNow)
   660  	if !nextTime.Equal(time.Date(2018, time.January, 1, 0, 0, 0, 0, volume.snapShotPolicy.location)) {
   661  		t.Fatalf("snapShotPolicy.schedule[5].next(timeNow) returned unexpected time: %v", nextTime)
   662  	}
   663  }
   664  
   665  func TestSnapShotPolicyNext(t *testing.T) {
   666  	var (
   667  		err                    error
   668  		testConfMap            conf.ConfMap
   669  		testConfMapStrings     []string
   670  		timeMidnight           time.Time
   671  		timeMidnightNext       time.Time
   672  		timeOhThirtyAM         time.Time
   673  		timeOneFortyFiveAM     time.Time
   674  		timeOneFortyFiveAMNext time.Time
   675  		timeTwoAM              time.Time
   676  		volume                 *volumeStruct
   677  	)
   678  
   679  	testConfMapStrings = []string{
   680  		"SnapShotSchedule:HalfPastTheHourSnapShotSchedule.CronTab=30 * * * *", // ==> snapShotPolicy.schedule[0]
   681  		"SnapShotSchedule:HalfPastTheHourSnapShotSchedule.Keep=99",
   682  		"SnapShotSchedule:TwoAMSnapShotSchedule.CronTab=0 2 * * *", //            ==> snapShotPolicy.schedule[1]
   683  		"SnapShotSchedule:TwoAMSnapShotSchedule.Keep=99",
   684  		"SnapShotPolicy:CommonSnapShotPolicy.ScheduleList=HalfPastTheHourSnapShotSchedule,TwoAMSnapShotSchedule",
   685  		"SnapShotPolicy:CommonSnapShotPolicy.TimeZone=America/Los_Angeles",
   686  		"Volume:TestVolume.SnapShotPolicy=CommonSnapShotPolicy",
   687  	}
   688  
   689  	testConfMap, err = conf.MakeConfMapFromStrings(testConfMapStrings)
   690  	if nil != err {
   691  		t.Fatalf("conf.MakeConfMapFromStrings() failed: %v", err)
   692  	}
   693  
   694  	volume = &volumeStruct{volumeName: "TestVolume", snapShotPolicy: nil}
   695  
   696  	err = volume.loadSnapShotPolicy(testConfMap)
   697  	if nil != err {
   698  		t.Fatalf("loadSnapShotPolicy() failed: %v", err)
   699  	}
   700  
   701  	timeMidnight = time.Date(2017, time.January, 1, 0, 0, 0, 0, volume.snapShotPolicy.location)
   702  	timeOhThirtyAM = time.Date(2017, time.January, 1, 0, 30, 0, 0, volume.snapShotPolicy.location)
   703  	timeOneFortyFiveAM = time.Date(2017, time.January, 1, 1, 45, 0, 0, volume.snapShotPolicy.location)
   704  	timeTwoAM = time.Date(2017, time.January, 1, 2, 0, 0, 0, volume.snapShotPolicy.location)
   705  
   706  	timeMidnightNext = volume.snapShotPolicy.schedule[0].next(timeMidnight)
   707  	timeOneFortyFiveAMNext = volume.snapShotPolicy.schedule[1].next(timeOneFortyFiveAM)
   708  
   709  	if timeMidnightNext != timeOhThirtyAM {
   710  		t.Fatalf("snapShotPolicy.schedule[0].next(timeMidnight) returned unexpected time: %v", timeMidnightNext)
   711  	}
   712  	if timeOneFortyFiveAMNext != timeTwoAM {
   713  		t.Fatalf("snapShotPolicy.schedule[1].next(timeOneFortyFiveAM) returned unexpected time: %v", timeOneFortyFiveAMNext)
   714  	}
   715  
   716  	timeMidnightNext = volume.snapShotPolicy.next(timeMidnight)
   717  	timeOneFortyFiveAMNext = volume.snapShotPolicy.next(timeOneFortyFiveAM)
   718  
   719  	if timeMidnightNext != timeOhThirtyAM {
   720  		t.Fatalf("snapShotPolicy.next(timeMidnight) returned unexpected time: %v", timeMidnightNext)
   721  	}
   722  	if timeOneFortyFiveAMNext != timeTwoAM {
   723  		t.Fatalf("snapShotPolicy.next(timeOneFortyFiveAM) returned unexpected time: %v", timeOneFortyFiveAMNext)
   724  	}
   725  }