Ai
1 Star 0 Fork 1

mysnapcore/mysnapd

forked from tupelo-shen/mysnapd 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
schedule_test.go 37.17 KB
一键复制 编辑 原始数据 按行查看 历史
tupelo-shen 提交于 2022-11-07 22:32 +08:00 . fix: timeutil commit
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264
// -*- Mode: Go; indent-tabs-mode: t -*-
/*
* Copyright (C) 2017 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package timeutil_test
import (
"strings"
"testing"
"time"
. "gopkg.in/check.v1"
"gitee.com/mysnapcore/mysnapd/timeutil"
)
func Test(t *testing.T) { TestingT(t) }
type timeutilSuite struct{}
var _ = Suite(&timeutilSuite{})
func (ts *timeutilSuite) TestClock(c *C) {
td := timeutil.Clock{Hour: 23, Minute: 59}
c.Check(td.Add(time.Minute), Equals, timeutil.Clock{Hour: 0, Minute: 0})
td = timeutil.Clock{Hour: 5, Minute: 34}
c.Check(td.Add(time.Minute), Equals, timeutil.Clock{Hour: 5, Minute: 35})
td = timeutil.Clock{Hour: 10, Minute: 1}
c.Check(td.Sub(timeutil.Clock{Hour: 10, Minute: 0}), Equals, time.Minute)
td = timeutil.Clock{Hour: 23, Minute: 0}
c.Check(td.Add(time.Hour), Equals, timeutil.Clock{Hour: 0, Minute: 0})
c.Check(td.Add(2*time.Hour), Equals, timeutil.Clock{Hour: 1, Minute: 0})
c.Check(td.Sub(timeutil.Clock{Hour: 1, Minute: 0}), Equals, 22*time.Hour)
c.Check(td.Sub(timeutil.Clock{Hour: 0, Minute: 0}), Equals, 23*time.Hour)
td = timeutil.Clock{Hour: 1, Minute: 0}
c.Check(td.Sub(timeutil.Clock{Hour: 23, Minute: 0}), Equals, -2*time.Hour)
c.Check(td.Sub(timeutil.Clock{Hour: 1, Minute: 0}), Equals, time.Duration(0))
td = timeutil.Clock{Hour: 0, Minute: 0}
c.Check(td.Sub(timeutil.Clock{Hour: 23, Minute: 0}), Equals, -1*time.Hour)
c.Check(td.Sub(timeutil.Clock{Hour: 1, Minute: 0}), Equals, -23*time.Hour)
}
func (ts *timeutilSuite) TestParseClock(c *C) {
for _, t := range []struct {
timeStr string
hour, minute int
errStr string
}{
{"8:59", 8, 59, ""},
{"08:59", 8, 59, ""},
{"12:00", 12, 0, ""},
{"xx", 0, 0, `cannot parse "xx"`},
{"11:61", 0, 0, `cannot parse "11:61"`},
{"25:00", 0, 0, `cannot parse "25:00"`},
} {
ti, err := timeutil.ParseClock(t.timeStr)
if t.errStr != "" {
c.Check(err, ErrorMatches, t.errStr)
} else {
c.Check(err, IsNil)
c.Check(ti.Hour, Equals, t.hour)
c.Check(ti.Minute, Equals, t.minute)
}
}
}
func (ts *timeutilSuite) TestScheduleString(c *C) {
for _, t := range []struct {
sched timeutil.Schedule
str string
}{
{
timeutil.Schedule{
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 13, Minute: 41}, End: timeutil.Clock{Hour: 14, Minute: 59}}},
},
"13:41-14:59",
}, {
timeutil.Schedule{
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 13, Minute: 41}, End: timeutil.Clock{Hour: 14, Minute: 59}},
},
WeekSpans: []timeutil.WeekSpan{
{Start: timeutil.Week{Weekday: time.Monday}, End: timeutil.Week{Weekday: time.Monday}}},
},
"mon,13:41-14:59",
}, {
timeutil.Schedule{
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 13, Minute: 41}, End: timeutil.Clock{Hour: 14, Minute: 59}, Spread: true}},
},
"13:41~14:59",
}, {
timeutil.Schedule{
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 6}, End: timeutil.Clock{Hour: 6}}},
WeekSpans: []timeutil.WeekSpan{
{Start: timeutil.Week{Weekday: time.Monday}, End: timeutil.Week{Weekday: time.Friday}}},
},
"mon-fri,06:00",
}, {
timeutil.Schedule{
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 6}, End: timeutil.Clock{Hour: 6}},
{Start: timeutil.Clock{Hour: 9}, End: timeutil.Clock{Hour: 14}, Spread: true, Split: 2}},
WeekSpans: []timeutil.WeekSpan{
{Start: timeutil.Week{Weekday: time.Monday}, End: timeutil.Week{Weekday: time.Friday}},
{Start: timeutil.Week{Weekday: time.Saturday}, End: timeutil.Week{Weekday: time.Saturday}}},
},
"mon-fri,sat,06:00,09:00~14:00/2",
}, {
timeutil.Schedule{
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 6}, End: timeutil.Clock{Hour: 6}}},
WeekSpans: []timeutil.WeekSpan{
{Start: timeutil.Week{Weekday: time.Monday, Pos: 1}, End: timeutil.Week{Weekday: time.Friday, Pos: 1}}},
},
"mon1-fri1,06:00",
}, {
timeutil.Schedule{
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 6}, End: timeutil.Clock{Hour: 6}}},
WeekSpans: []timeutil.WeekSpan{
{Start: timeutil.Week{Weekday: time.Monday, Pos: 5},
End: timeutil.Week{Weekday: time.Monday, Pos: 5}}},
},
"mon5,06:00",
}, {
timeutil.Schedule{
WeekSpans: []timeutil.WeekSpan{
{Start: timeutil.Week{Weekday: time.Monday}, End: timeutil.Week{Weekday: time.Monday}}},
},
"mon",
}, {
timeutil.Schedule{
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 6}, End: timeutil.Clock{Hour: 9}, Spread: true, Split: 2}},
},
"06:00~09:00/2",
},
} {
c.Check(t.sched.String(), Equals, t.str)
}
}
func (ts *timeutilSuite) TestParseLegacySchedule(c *C) {
for _, t := range []struct {
in string
expected []*timeutil.Schedule
errStr string
}{
// invalid
{"", nil, `cannot parse "": not a valid interval`},
{"invalid-11:00", nil, `cannot parse "invalid": not a valid time`},
{"9:00-11:00/invalid", nil, `cannot parse "invalid": not a valid interval`},
{"09:00-25:00", nil, `cannot parse "25:00": not a valid time`},
{"09:00-24:30", nil, `cannot parse "24:30": not a valid time`},
// valid
{"9:00-11:00", []*timeutil.Schedule{
{ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 9}, End: timeutil.Clock{Hour: 11}, Spread: true}}},
}, ""},
{"9:00-11:00/20:00-22:00", []*timeutil.Schedule{
{ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 9}, End: timeutil.Clock{Hour: 11}, Spread: true}}},
{ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 20}, End: timeutil.Clock{Hour: 22}, Spread: true}}},
}, ""},
} {
c.Logf("trying: %v", t)
schedule, err := timeutil.ParseLegacySchedule(t.in)
if t.errStr != "" {
c.Check(err, ErrorMatches, t.errStr, Commentf("%q returned unexpected error: %s", t.in, err))
} else {
c.Check(err, IsNil, Commentf("%q returned error: %s", t.in, err))
c.Check(schedule, DeepEquals, t.expected, Commentf("%q failed", t.in))
}
}
}
func parse(c *C, s string) (time.Duration, time.Duration) {
l := strings.Split(s, "-")
c.Assert(l, HasLen, 2)
a, err := time.ParseDuration(l[0])
c.Assert(err, IsNil)
b, err := time.ParseDuration(l[1])
c.Assert(err, IsNil)
return a, b
}
const (
maxDuration = 60 * 24 * time.Hour
)
func (ts *timeutilSuite) TestLegacyScheduleNext(c *C) {
const shortForm = "2006-01-02 15:04"
for _, t := range []struct {
schedule string
last string
now string
next string
}{
{
// daily schedule, missed one window
// -> run next daily window
schedule: "9:00-11:00/21:00-23:00",
last: "2017-02-05 22:00",
now: "2017-02-06 20:00",
next: "1h-3h",
},
{
// daily schedule, used one window
// -> run next daily window
schedule: "9:00-11:00/21:00-23:00",
last: "2017-02-06 10:00",
now: "2017-02-06 20:00",
next: "1h-3h",
},
{
// daily schedule, missed all todays windows
// run tomorrow
schedule: "9:00-11:00/21:00-22:00",
last: "2017-02-04 21:30",
now: "2017-02-06 23:00",
next: "10h-12h",
},
{
// single daily schedule, already updated today
schedule: "9:00-11:00",
last: "2017-02-06 09:30",
now: "2017-02-06 10:00",
next: "23h-25h",
},
{
// single daily schedule, already updated today
// (at exactly the edge)
schedule: "9:00-11:00",
last: "2017-02-06 09:00",
now: "2017-02-06 09:00",
next: "24h-26h",
},
{
// single daily schedule, last update a day ago
// now is within the update window so randomize
// (run within remaining time delta)
schedule: "9:00-11:00",
last: "2017-02-05 09:30",
now: "2017-02-06 10:00",
next: "0-55m",
},
{
// multi daily schedule, already updated today
schedule: "9:00-11:00/21:00-22:00",
last: "2017-02-06 21:30",
now: "2017-02-06 23:00",
next: "10h-12h",
},
{
// daily schedule, very small window
schedule: "9:00-9:03",
last: "2017-02-05 09:02",
now: "2017-02-06 08:58",
next: "2m-5m",
},
{
// daily schedule, zero window
schedule: "9:00-9:00",
last: "2017-02-05 09:02",
now: "2017-02-06 08:58",
next: "2m-2m",
},
} {
last, err := time.ParseInLocation(shortForm, t.last, time.Local)
c.Assert(err, IsNil)
fakeNow, err := time.ParseInLocation(shortForm, t.now, time.Local)
c.Assert(err, IsNil)
restorer := timeutil.MockTimeNow(func() time.Time {
return fakeNow
})
defer restorer()
sched, err := timeutil.ParseLegacySchedule(t.schedule)
c.Assert(err, IsNil)
minDist, maxDist := parse(c, t.next)
next := timeutil.Next(sched, last, maxDuration)
c.Check(next >= minDist && next <= maxDist, Equals, true, Commentf("invalid distance for schedule %q with last refresh %q, now %q, expected %v, got %v", t.schedule, t.last, t.now, t.next, next))
}
}
func (ts *timeutilSuite) TestParseSchedule(c *C) {
for _, t := range []struct {
in string
expected []*timeutil.Schedule
errStr string
}{
// invalid
{"", nil, `cannot parse "": not a valid fragment`},
{"invalid-11:00", nil, `cannot parse "invalid-11:00": not a valid time`},
{"9:00-11:00/invalid", nil, `cannot parse "9:00-11:00/invalid": not a valid interval`},
{"9:00-11:00/0", nil, `cannot parse "9:00-11:00/0": not a valid interval`},
{"09:00-25:00", nil, `cannot parse "09:00-25:00": not a valid time`},
{"09:00-24:30", nil, `cannot parse "09:00-24:30": not a valid time`},
{"mon-01:00", nil, `cannot parse "mon-01:00": not a valid time`},
{"9:00-mon@11:00", nil, `cannot parse "9:00-mon@11:00": not a valid time`},
{"9:00,mon", nil, `cannot parse "mon": invalid schedule fragment`},
{"mon~wed", nil, `cannot parse "mon~wed": "mon~wed" is not a valid weekday`},
{"mon--wed", nil, `cannot parse "mon--wed": invalid week span`},
{"mon-wed/2,,9:00", nil, `cannot parse "mon-wed/2": "wed/2" is not a valid weekday`},
{"mon..wed", nil, `cannot parse "mon..wed": "mon..wed" is not a valid weekday`},
{"mon9,9:00", nil, `cannot parse "mon9": "mon9" is not a valid weekday`},
{"mon0,9:00", nil, `cannot parse "mon0": "mon0" is not a valid weekday`},
{"mon5-mon1,9:00", nil, `cannot parse "mon5-mon1": unsupported schedule`},
{"mon%,9:00", nil, `cannot parse "mon%": "mon%" is not a valid weekday`},
{"foo2,9:00", nil, `cannot parse "foo2": "foo2" is not a valid weekday`},
{"9:00---11:00", nil, `cannot parse "9:00---11:00": not a valid time`},
{"9:00-11:00/3/3/3", nil, `cannot parse "9:00-11:00/3/3/3": not a valid interval`},
{"9:00-11:00///3", nil, `cannot parse "9:00-11:00///3": not a valid interval`},
{"9:00-9:00-10:00/3", nil, `cannot parse "9:00-9:00-10:00/3": not a valid time`},
{"9:00,,,9:00-10:00/3", nil, `cannot parse ",9:00-10:00/3": not a valid fragment`},
{",,,", nil, `cannot parse "": not a valid fragment`},
{",,", nil, `cannot parse "": not a valid fragment`},
{":", nil, `cannot parse ":": not a valid time`},
{"-", nil, `cannot parse "-": "" is not a valid weekday`},
{"-/4", nil, `cannot parse "-/4": "" is not a valid weekday`},
{"~/4", nil, `cannot parse "~/4": "~/4" is not a valid weekday`},
// valid
{
in: "9:00-11:00",
expected: []*timeutil.Schedule{{
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 9}, End: timeutil.Clock{Hour: 11}}}}},
}, {
in: "9:00-11:00/2",
expected: []*timeutil.Schedule{{
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 9}, End: timeutil.Clock{Hour: 11}, Split: 2}}}},
}, {
in: "mon,9:00-11:00",
expected: []*timeutil.Schedule{{
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 9}, End: timeutil.Clock{Hour: 11}}},
WeekSpans: []timeutil.WeekSpan{
{Start: timeutil.Week{Weekday: time.Monday}, End: timeutil.Week{Weekday: time.Monday}}},
}},
}, {
in: "fri,mon,9:00-11:00",
expected: []*timeutil.Schedule{{
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 9}, End: timeutil.Clock{Hour: 11}}},
WeekSpans: []timeutil.WeekSpan{
{Start: timeutil.Week{Weekday: time.Friday}, End: timeutil.Week{Weekday: time.Friday}},
{Start: timeutil.Week{Weekday: time.Monday}, End: timeutil.Week{Weekday: time.Monday}}},
}},
}, {
in: "9:00-11:00,,20:00-22:00",
expected: []*timeutil.Schedule{{
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 9}, End: timeutil.Clock{Hour: 11}}},
}, {
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 20}, End: timeutil.Clock{Hour: 22}}}},
},
}, {
in: "mon,9:00-11:00,,wed,22:00-23:00",
expected: []*timeutil.Schedule{{
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 9}, End: timeutil.Clock{Hour: 11}}},
WeekSpans: []timeutil.WeekSpan{
{Start: timeutil.Week{Weekday: time.Monday}, End: timeutil.Week{Weekday: time.Monday}}},
}, {
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 22}, End: timeutil.Clock{Hour: 23}}},
WeekSpans: []timeutil.WeekSpan{
{Start: timeutil.Week{Weekday: time.Wednesday}, End: timeutil.Week{Weekday: time.Wednesday}}},
}},
}, {
in: "mon,9:00,10:00,14:00,15:00",
expected: []*timeutil.Schedule{{
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 9}, End: timeutil.Clock{Hour: 9}},
{Start: timeutil.Clock{Hour: 10}, End: timeutil.Clock{Hour: 10}},
{Start: timeutil.Clock{Hour: 14}, End: timeutil.Clock{Hour: 14}},
{Start: timeutil.Clock{Hour: 15}, End: timeutil.Clock{Hour: 15}}},
WeekSpans: []timeutil.WeekSpan{
{Start: timeutil.Week{Weekday: time.Monday}, End: timeutil.Week{Weekday: time.Monday}}},
}},
}, {
in: "mon,wed",
expected: []*timeutil.Schedule{{
WeekSpans: []timeutil.WeekSpan{
{Start: timeutil.Week{Weekday: time.Monday}, End: timeutil.Week{Weekday: time.Monday}},
{Start: timeutil.Week{Weekday: time.Wednesday}, End: timeutil.Week{Weekday: time.Wednesday}}},
}},
}, {
// same as above
in: "mon,,wed",
expected: []*timeutil.Schedule{{
WeekSpans: []timeutil.WeekSpan{
{Start: timeutil.Week{Weekday: time.Monday}, End: timeutil.Week{Weekday: time.Monday}}},
}, {
WeekSpans: []timeutil.WeekSpan{
{Start: timeutil.Week{Weekday: time.Wednesday}, End: timeutil.Week{Weekday: time.Wednesday}}}},
},
}, {
// but not the same as this one
in: "mon-wed",
expected: []*timeutil.Schedule{{
WeekSpans: []timeutil.WeekSpan{
{Start: timeutil.Week{Weekday: time.Monday}, End: timeutil.Week{Weekday: time.Wednesday}}},
}},
}, {
in: "mon-wed,fri,9:00-11:00/2",
expected: []*timeutil.Schedule{{
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 9}, End: timeutil.Clock{Hour: 11}, Split: 2},
},
WeekSpans: []timeutil.WeekSpan{
{Start: timeutil.Week{Weekday: time.Monday}, End: timeutil.Week{Weekday: time.Wednesday}},
{Start: timeutil.Week{Weekday: time.Friday}, End: timeutil.Week{Weekday: time.Friday}},
},
}},
}, {
in: "9:00~11:00",
expected: []*timeutil.Schedule{{
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 9}, End: timeutil.Clock{Hour: 11}, Spread: true}},
}},
}, {
in: "9:00",
expected: []*timeutil.Schedule{{
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 9}, End: timeutil.Clock{Hour: 9}}},
}},
}, {
in: "mon1,9:00",
expected: []*timeutil.Schedule{{
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 9}, End: timeutil.Clock{Hour: 9}}},
WeekSpans: []timeutil.WeekSpan{
{Start: timeutil.Week{Weekday: time.Monday, Pos: 1}, End: timeutil.Week{Weekday: time.Monday, Pos: 1}}},
}},
}, {
in: "00:00-24:00",
expected: []*timeutil.Schedule{{
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 0}, End: timeutil.Clock{Hour: 24}}},
}},
}, {
in: "23:00-01:00",
expected: []*timeutil.Schedule{{
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 23}, End: timeutil.Clock{Hour: 1}},
},
}},
}, {
in: "fri-mon",
expected: []*timeutil.Schedule{{
WeekSpans: []timeutil.WeekSpan{
{Start: timeutil.Week{Weekday: time.Friday}, End: timeutil.Week{Weekday: time.Monday}}},
}},
}, {
in: "mon-mon2,9:00",
expected: []*timeutil.Schedule{{
ClockSpans: []timeutil.ClockSpan{
{Start: timeutil.Clock{Hour: 9}, End: timeutil.Clock{Hour: 9}}},
WeekSpans: []timeutil.WeekSpan{
{Start: timeutil.Week{Weekday: time.Monday}, End: timeutil.Week{Weekday: time.Monday, Pos: 2}}},
}},
},
} {
c.Logf("trying %+v", t)
schedule, err := timeutil.ParseSchedule(t.in)
if t.errStr != "" {
c.Check(err, ErrorMatches, t.errStr, Commentf("%q returned unexpected error: %s", t.in, err))
} else {
c.Check(err, IsNil, Commentf("%q returned error: %s", t.in, err))
c.Check(schedule, DeepEquals, t.expected, Commentf("%q failed", t.in))
}
}
}
func (ts *timeutilSuite) TestScheduleNext(c *C) {
const shortForm = "2006-01-02 15:04"
for _, t := range []struct {
schedule string
last string
now string
next string
randomized bool
}{
{
schedule: "mon,10:00,,fri,15:00",
// sun 22:00
last: "2017-02-05 22:00",
// mon 9:00
now: "2017-02-06 9:00",
next: "1h-1h",
}, {
// first monday of the month, at 10:00
schedule: "mon1,10:00",
// Sun 22:00
last: "2017-02-05 22:00",
// Mon 9:00
now: "2017-02-06 9:00",
next: "1h-1h",
}, {
// first Monday of the month, at 10:00
schedule: "mon1,10:00",
// first Monday of the month, 10:00
last: "2017-02-06 10:00",
// first Monday of the month, 11:00, right after
// 'previous first Monday' run
now: "2017-02-06 11:00",
// expecting March, 6th, 10:00, 27 days and 23 hours
// from now
next: "671h-671h",
}, {
// second Monday of the month, at 10:00
schedule: "mon2,10:00",
// first Monday of the month, 10:00
last: "2017-02-06 10:00",
// first Monday of the month, 11:00, right after
// 'previous first Monday' run
now: "2017-02-06 11:00",
// expecting February, 13, 10:00, 6 days and 23 hours
// from now
next: "167h-167h",
}, {
// last Monday of the month, at 10:00
schedule: "mon5,10:00",
// first Monday of the month, 10:00
last: "2017-02-06 10:00",
// first Monday of the month, 11:00, right after
// 'previous first Monday' run
now: "2017-02-06 11:00",
// expecting February, 27th, 10:00, 20 days and 23 hours
// from now
next: "503h-503h",
}, {
// (deprecated syntax, interpreted as mon1-tue)
// from the first Monday of the month to the second Tuesday of
// the month, at 10:00
schedule: "mon1-tue2,10:00",
// Monday, 10:00
last: "2017-02-06 10:00",
// Tuesday, the day after the first Monday of the month
now: "2017-02-07 11:00",
// expecting to run on 03.06.2017
next: "647h-647h",
}, {
// from the first Monday of the month to the following Tuesday of
// the month, at 10:00
schedule: "mon1-tue,10:00",
last: "2017-02-01 10:00",
// Sunday, 10:00
now: "2017-02-05 10:00",
// expecting to run the next day at 10:00
next: "24h-24h",
}, {
// from the first Monday of the month to the following Tuesday of
// the month, at 10:00
schedule: "mon1-tue,10:00",
// Tuesday, 10:00
last: "2017-02-14 22:00",
// Thursday, 10:00
now: "2017-02-16 10:00",
// expecting to run in 18 days
next: "432h-432h",
}, {
// from the first Monday of the month to the following Tuesday of
// the month, at 10:00
schedule: "mon1-tue,10:00",
// Sunday, 22:00
last: "2017-02-05 22:00",
// first Monday of the month
now: "2017-02-06 11:00",
// expecting to run the next day at 10:00
next: "23h-23h",
}, {
// from the first Monday of the month to the following Tuesday of
// the month, at 10:00
schedule: "mon1-tue,10:00-12:00",
// Sunday, 22:00
last: "2017-02-05 22:00",
// first Monday of the month, within the update window
now: "2017-02-06 11:00",
// expecting to run now
next: "0h-0h",
}, {
// from the first Monday of the month to the following Tuesday of
// the month, at 10:00
schedule: "mon1-tue,10:00~12:00",
// Sunday, 22:00
last: "2017-02-05 22:00",
// first Monday of the month, within the update window
now: "2017-02-06 11:00",
// expecting to run now
next: "0h-1h",
// since we're in update window we'll run now regardless
// of 'spreading'
randomized: false,
}, {
schedule: "mon,10:00~12:00,,fri,15:00",
last: "2017-02-05 22:00",
now: "2017-02-06 9:00",
next: "1h-3h",
randomized: true,
}, {
schedule: "mon,10:00-12:00,,fri,15:00",
last: "2017-02-06 12:00",
// tue 12:00
now: "2017-02-07 12:00",
// 3 days and 3 hours from now
next: "75h-75h",
}, {
// randomized between 10:00 and 12:00
schedule: "mon,10:00~12:00",
// sun 22:00
last: "2017-02-05 22:00",
// mon 9:00
now: "2017-02-06 9:00",
next: "1h-3h",
randomized: true,
}, {
// Friday to Monday, 10am
schedule: "fri-mon,10:00",
// sun 22:00
last: "2017-02-05 22:00",
// mon 9:00
now: "2017-02-06 9:00",
next: "1h-1h",
}, {
// Friday to Monday, 10am
schedule: "fri-mon,10:00",
// mon 10:00
last: "2017-02-06 10:00",
// mon 10:00
now: "2017-02-06 10:00",
// 4 days from now
next: "96h-96h",
}, {
// Wednesday to Friday, 10am
schedule: "wed-fri,10:00",
// mon 10:00
last: "2017-02-06 10:00",
// mon 10:00
now: "2017-02-06 10:00",
// 2 days from now
next: "48h-48h",
}, {
// randomized, once a day
schedule: "0:00~24:00",
// sun 22:00
last: "2017-02-05 22:00",
// mon 9:00
now: "2017-02-05 23:00",
next: "1h-25h",
randomized: true,
}, {
// randomized, once a day
schedule: "0:00~24:00",
// mon 10:00
last: "2017-02-06 10:00",
// mon 11:00
now: "2017-02-06 11:00",
// sometime the next day
next: "13h-37h",
randomized: true,
}, {
// during the night, 23:00-1:00
schedule: "23:00~1:00",
// mon 10:00
last: "2017-02-06 10:00",
// mon 11:00
now: "2017-02-06 22:00",
// sometime over the night
next: "1h-3h",
randomized: true,
}, {
// during the night, 23:00-1:00
schedule: "23:00~1:00",
// Mon 23:00
last: "2017-02-06 23:00",
// Tue 0:00
now: "2017-02-07 00:00",
// sometime over the night
next: "23h-25h",
randomized: true,
}, {
// twice between 9am and 11am
schedule: "9:00-11:00/2",
// last attempt at the beginning of window
last: "2017-02-06 9:00",
// sometime between 10am and 11am
now: "2017-02-06 9:30",
next: "30m-90m",
}, {
// 2 ranges
schedule: "9:00-10:00,10:00-11:00",
// last attempt at the beginning of window
last: "2017-02-06 9:01",
// next one at 10am
now: "2017-02-06 9:30",
next: "30m-30m",
}, {
// twice, at 9am and at 2pm
schedule: "9:00,14:00",
// last right after scheduled time window
last: "2017-02-06 9:01",
// next one at 2pm
now: "2017-02-06 9:30",
next: "270m-270m",
}, {
// 2 ranges, reversed order in spec
schedule: "10:00~11:00,9:00-10:00",
// last attempt at the beginning of window
last: "2017-02-06 9:01",
// sometime between 10am and 11am
now: "2017-02-06 9:30",
next: "30m-90m",
randomized: true,
}, {
// first Wednesday at 13:00
schedule: "wed1,13:00",
now: "2018-07-30 9:00",
// yesterday
last: "2018-07-29 13:00",
// next one on 2018-08-01 13:00
next: "52h-52h",
}, {
// October 2019
// Su Mo Tu We Th Fr Sa
// 29 30| 1 2 3 4 5
// 6 7 8 9 10 11 12
// 13 14 15 16 17 18 19
// 20 21 22 23 24 25 26
// 27 28 29 30 31
// first Monday to the following Wednesday of the month, in Oct
// 2019, matches 07.10-09.10
schedule: "mon1-wed,9:00-13:00",
now: "2019-09-30 9:00",
// yesterday
last: "2019-09-30 9:00",
// next one on 2019-10-07 9:00
next: "168h-168h",
}, {
// first Monday to the following Wednesday of the month, in Oct
// 2019, matches 30.09-04.10
schedule: "mon-fri1,9:00-13:00",
now: "2019-09-29 9:00",
last: "2019-09-29 9:00",
// next one on 2019-09-30 9:00
next: "24h-24h",
}, {
// most trivial case
schedule: "21:00-22:00",
now: "2019-09-29 8:00",
last: "2019-09-28 21:05",
// next one on 2019-09-29 at 21:00
next: "13h-13h",
},
} {
c.Logf("trying %+v", t)
last, err := time.ParseInLocation(shortForm, t.last, time.Local)
c.Assert(err, IsNil)
fakeNow, err := time.ParseInLocation(shortForm, t.now, time.Local)
c.Assert(err, IsNil)
restorer := timeutil.MockTimeNow(func() time.Time {
return fakeNow
})
defer restorer()
sched, err := timeutil.ParseSchedule(t.schedule)
c.Assert(err, IsNil)
// keep track of previous result for tests where event time is
// randomized
previous := time.Duration(0)
calls := 2
for i := 0; i < calls; i++ {
next := timeutil.Next(sched, last, maxDuration)
if t.randomized {
c.Check(next, Not(Equals), previous)
} else if previous != 0 {
// not randomized and not the first run
c.Check(next, Equals, previous)
}
c.Logf("next: %v", next)
minDist, maxDist := parse(c, t.next)
c.Check(next >= minDist && next <= maxDist,
Equals, true,
Commentf("invalid distance for schedule %q with last refresh %q, now %q, expected %v, got %v, date %s",
t.schedule, t.last, t.now, t.next, next, fakeNow.Add(next)))
previous = next
}
}
}
func (ts *timeutilSuite) TestScheduleIncludes(c *C) {
const shortForm = "2006-01-02 15:04:05"
for _, t := range []struct {
schedule string
now string
expecting bool
}{
{
schedule: "mon,10:00,,fri,15:00",
// mon 9:00
now: "2017-02-06 9:00:00",
expecting: false,
}, {
// first monday of the month, at 10:00
schedule: "mon1,10:00",
// Mon 10:00:00
now: "2017-02-06 10:00:00",
expecting: true,
}, {
// first monday of the month, at 10:00
schedule: "mon1,10:00",
// Mon 10:00:45
now: "2017-02-06 10:00:45",
expecting: true,
}, {
// first monday of the month, at 10:00
schedule: "mon1,10:00",
// Mon 10:01
now: "2017-02-06 10:01:00",
expecting: false,
}, {
// last Monday of the month, at 10:00
schedule: "mon5,10:00-11:00",
// first Monday of the month, 11:00, right after
// 'previous first Monday' run
now: "2017-02-27 10:59:20",
expecting: true,
}, {
// (deprecated syntax)
// from first Monday of the month to the second Tuesday of
// the month, at 10:00 to 12:00
schedule: "mon1-tue2,10:00-12:00",
// Thursday, 11:10
now: "2017-02-09 11:10:00",
expecting: false,
}, {
// from first Monday of the month to the following Tuesday of
// the month, at 10:00 to 12:00
schedule: "mon1-tue,10:00~12:00",
// Thursday, 11:10
now: "2017-02-02 11:10:00",
expecting: false,
}, {
// from first Monday of the month to the following Tuesday of
// the month, at 10:00 to 12:00
schedule: "mon1-tue,10:00~12:00",
// Monday, 11:10
now: "2017-02-06 11:10:00",
expecting: true,
}, {
// from first Monday of the month to the following Tuesday of
// the month, at 10:00 to 12:00
schedule: "mon1-tue,10:00~12:00",
// Thursday, 11:10
now: "2017-02-16 11:10:00",
expecting: false,
}, {
// from first Monday of the month to the following Tuesday of
// the month, at 10:00 to 12:00
schedule: "mon1-tue,10:00~12:00",
// Thursday, 11:10
now: "2017-03-06 11:10:00",
expecting: true,
}, {
// from first Monday of the month to the following Tuesday of
// the month, at 10:00 to 12:00
schedule: "mon1-tue,10:00~12:00",
// Thursday, 11:10
now: "2017-02-09 11:10:00",
expecting: false,
}, {
// from first Tuesday of the month to the following Monday of
// the month, at 10:00 to 12:00
schedule: "tue1-mon,10:00~12:00",
// Thursday, 11:10
now: "2017-02-09 11:10:00",
expecting: true,
}, {
// (deprecated syntax)
// from 4th Monday of the month to the following Wednesday of
// the month, at 10:00 to 12:00
schedule: "mon4-wed5,10:00~12:00",
// Schedule ends up being Feb 27 - Mar 01 2017
now: "2017-03-02 11:10:00",
expecting: false,
}, {
// from last Monday of the month to the following Wednesday of
// the month, at 10:00 to 12:00
schedule: "mon5-wed,10:00~12:00",
// Schedule ends up being Feb 27 - Mar 01 2017
now: "2017-03-01 11:10:00",
expecting: true,
}, {
// from last Monday of the month to the following Wednesday of
// the month, at 10:00 to 12:00
schedule: "mon5-wed,10:00~12:00",
// Schedule ends up being Feb 27 - Mar 01 2017
now: "2017-03-02 11:10:00",
expecting: false,
}, {
// (deprecated syntax)
// from last Monday of the month to the following Tuesday of
// the month, at 10:00
schedule: "mon1-tue2,10:00~12:00",
// Sunday, 11:10
now: "2017-02-05 11:10:00",
expecting: false,
}, {
// twice between 9am and 11am
schedule: "9:00-11:00/2",
now: "2017-02-06 10:30:00",
expecting: true,
}, {
schedule: "9:00-10:00,10:00-11:00",
now: "2017-02-06 10:30:00",
expecting: true,
}, {
// every day, 23:59
schedule: "23:59",
now: "2017-02-06 23:59:59",
expecting: true,
}, {
// 2 ranges, reversed order in spec
schedule: "10:00~11:00,9:00-10:00",
// sometime between 10am and 11am
now: "2017-02-06 9:30:00",
expecting: true,
}, {
schedule: "mon1-wed,9:00-10:00",
// Tue, 9:30
now: "2019-10-08 9:30:00",
expecting: true,
}, {
schedule: "tue1,9:00-10:00",
// Tue, 9:30
now: "2019-10-01 9:30:00",
expecting: true,
},
} {
c.Logf("trying %+v", t)
now, err := time.ParseInLocation(shortForm, t.now, time.Local)
c.Assert(err, IsNil)
sched, err := timeutil.ParseSchedule(t.schedule)
c.Assert(err, IsNil)
c.Check(timeutil.Includes(sched, now), Equals, t.expecting,
Commentf("unexpected result for schedule %v and time %v", t.schedule, now))
}
}
func (ts *timeutilSuite) TestClockSpans(c *C) {
for _, t := range []struct {
clockspan string
flattenend []string
}{
{
clockspan: "23:00-01:00/2",
flattenend: []string{"23:00-00:00", "00:00-01:00"},
}, {
clockspan: "23:00-01:00/4",
flattenend: []string{"23:00-23:30", "23:30-00:00", "00:00-00:30", "00:30-01:00"},
},
} {
c.Logf("trying %+v", t)
spans, err := timeutil.ParseClockSpan(t.clockspan)
c.Assert(err, IsNil)
spanStrings := make([]string, len(t.flattenend))
flattened := spans.ClockSpans()
c.Assert(flattened, HasLen, len(t.flattenend))
for i := range flattened {
spanStrings[i] = flattened[i].String()
}
c.Assert(spanStrings, DeepEquals, t.flattenend)
}
}
func (ts *timeutilSuite) TestWeekSpans(c *C) {
const shortForm = "2006-01-02"
// July 2018 August 2018
// Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
// 1 2 3 4 5 6 7 1 2 3 4
// 8 9 10 11 12 13 14 5 6 7 8 9 10 11
// 15 16 17 18 19 20 21 12 13 14 15 16 17 18
// 22 23 24 25 26 27 28 19 20 21 22 23 24 25
// 29 30 31 26 27 28 29 30 31
for _, t := range []struct {
week string
when string
match bool
}{
{
// first Wednesday
week: "wed1",
when: "2018-08-01",
match: true,
}, {
// first Wednesday
week: "wed1",
// actually 2nd Wednesday
when: "2018-08-08",
match: false,
}, {
// second Wednesday
week: "wed2",
when: "2018-08-08",
match: true,
}, {
// first Tuesday
week: "tue1",
when: "2018-08-07",
match: true,
}, {
// first Sunday
week: "sun1",
when: "2018-07-01",
match: true,
}, {
// last Tuesday
week: "tue5",
when: "2018-07-31",
match: true,
}, {
// last Tuesday
week: "tue5",
when: "2018-07-24",
match: false,
}, {
// last Thursday
week: "thu5",
when: "2018-07-26",
match: true,
}, {
// using deprecated syntax
// first Monday (06.08) to first Friday (03.08), see August calendar above
// includes: 01.08-03.08 and 06.08-07.08
week: "mon1-fri1",
// Wednesday
when: "2018-08-01",
match: false,
}, {
// using deprecated syntax
// first Monday (06.08) to first Friday (03.08), see August calendar above
week: "mon1-fri",
// Tuesday
when: "2018-08-07",
match: true,
}, {
// first Monday (06.08) to first Friday (03.08), see August calendar above
week: "mon1-fri",
// Thursday
when: "2018-08-08",
match: true,
}, {
// second Monday (13.08) to second Friday (10.08), see August calendar above
// includes: 13.08-14.08 and 08.08-10.08
week: "mon2-fri",
// Thursday
when: "2018-08-13",
match: true,
}, {
// second Monday (13.08) to second Friday (10.08), see August calendar above
week: "mon2-fri",
// Thursday
when: "2018-08-13",
match: true,
}, {
// first Friday (03.08) to the following Monday (06.08), see August calendar above
// includes: 03.08-06.08
week: "fri1-mon",
// Saturday
when: "2018-08-04",
match: true,
}, {
// first Friday (06.07) to the following Monday (09.07), see July calendar above
// includes: 03.07-09.07
week: "fri1-mon",
// Sunday
when: "2018-07-08",
match: true,
}, {
// first Friday (03.08) to the preceding Monday (30.07), see July. August calendar above
// includes: 30.07-03.08
week: "mon-fri1",
// Saturday
when: "2018-08-01",
match: true,
}, {
// first Friday (03.08) to the preceding Monday (30.07), see July. August calendar above
// includes: 30.07-03.08
week: "mon-fri1",
// Saturday
when: "2018-07-30",
match: true,
}, {
// 4th Friday (27.08) to the following Monday (02.08), see July. August calendar above
// includes: 27.07-02.08
week: "fri4-thu",
// Saturday
when: "2018-08-01",
match: true,
}, {
// using deprecated syntax
// first Friday (06.07) to the following Monday (09.07), see July calendar above
// includes: 03.07-09.07
week: "fri1-mon1",
// Sunday
when: "2018-07-08",
match: true,
}, {
// first Friday (06.07) to the following Monday (09.07), see July calendar above
// includes: 06.07-09.07
week: "fri1-mon",
// Sunday
when: "2018-07-15",
match: false,
}, {
// last Monday (30.07) to the following Friday (03.07), see July calendar above
// includes: 03.07-03.08
week: "mon5-fri",
// Sunday
when: "2018-07-31",
match: true,
}, {
// last Friday (27.07) to the preceding Monday (23.07), see July calendar above
// includes: 23.07-27.07
week: "mon-fri5",
// Sunday
when: "2018-07-28",
match: false,
}, {
// last Friday (27.07) to the preceding Monday (23.07), see July calendar above
// includes: 23.07-27.07
week: "mon-fri5",
// Sunday
when: "2018-07-25",
match: true,
}, {
// first Monday (2.07) to the following Monday (9.07), see July calendar above
// includes: 2.07-9.07
week: "mon1-mon",
// Tuesday
when: "2018-07-03",
match: true,
}, {
week: "mon1-mon",
// Monday (the farther edge of the span)
when: "2018-07-09",
match: true,
}, {
week: "mon1-mon",
// Tuesday
when: "2018-07-10",
match: false,
},
} {
c.Logf("trying %+v", t)
ws, err := timeutil.ParseWeekSpan(t.week)
c.Assert(err, IsNil)
when, err := time.ParseInLocation(shortForm, t.when, time.Local)
c.Assert(err, IsNil)
c.Logf("when: %v %s", when, when.Weekday())
c.Check(ws.Match(when), Equals, t.match)
}
}
func (ts *timeutilSuite) TestTimeZero(c *C) {
// test with a zero time stamp to make sure that code does not do
// anything silly
// zero time is: time is: 0001-01-01 00:00:00 +0000 UTC and ... Monday
zero := time.Time{}
c.Logf("time is: %v weekday: %v", zero, zero.Weekday())
for _, schedule := range []string{
"mon-tue,0:00-12:00",
"mon1-tue,0:00-12:00",
"mon-tue1,0:00-12:00",
} {
c.Logf("trying: %v", schedule)
sch, err := timeutil.ParseSchedule(schedule)
c.Assert(err, IsNil)
c.Check(timeutil.Includes(sch, zero), Equals, true)
c.Check(timeutil.Includes(sch, zero.Add(5*time.Hour)), Equals, true)
// wednesday
c.Check(timeutil.Includes(sch, zero.Add(2*24*time.Hour)), Equals, false)
}
}
func (ts *timeutilSuite) TestMonthNext(c *C) {
const shortForm = "2006-01-02"
for _, t := range []struct {
when, next string
}{
{"2018-07-01", "2018-08-01"},
{"2018-07-31", "2018-08-01"},
{"2018-07-20", "2018-08-01"},
{"2018-02-01", "2018-03-01"},
{"2018-02-28", "2018-03-01"},
{"2018-01-31", "2018-02-01"},
// in 2020 Feb is 29 days
{"2020-01-31", "2020-02-01"},
{"2020-02-01", "2020-03-01"},
{"2020-02-14", "2020-03-01"},
} {
when, err := time.ParseInLocation(shortForm, t.when, time.Local)
c.Assert(err, IsNil)
c.Logf("when: %v expecting: %v", when, t.next)
next := timeutil.MonthNext(when)
c.Check(next.Format(shortForm), Equals, t.next)
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/mysnapcore/mysnapd.git
git@gitee.com:mysnapcore/mysnapd.git
mysnapcore
mysnapd
mysnapd
v0.1.0

搜索帮助