Skip to content

Commit

Permalink
Merge pull request #14 from adhocore/13-faulty-past-year
Browse files Browse the repository at this point in the history
Fix faulty past year check, improve tests
  • Loading branch information
adhocore authored Nov 8, 2022
2 parents 6f55218 + 0106413 commit 1c36643
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 29 deletions.
38 changes: 22 additions & 16 deletions cmd/tasker/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,40 +9,46 @@ import (
"github.com/adhocore/gronx/pkg/tasker"
)

var exit = os.Exit
var tick = time.Minute

var opt tasker.Option

func init() {
flag.StringVar(&opt.File, "file", "", "The task file in crontab format (without user)")
flag.StringVar(&opt.Tz, "tz", "Local", "The timezone to use for tasks")
flag.StringVar(&opt.Shell, "shell", tasker.Shell()[0], "The shell to use for running tasks")
flag.StringVar(&opt.Out, "out", "", "The fullpath to file where output from tasks are sent to")
flag.BoolVar(&opt.Verbose, "verbose", false, "The verbose mode outputs as much as possible")
flag.Int64Var(&opt.Until, "until", 0, "The timeout for task daemon in minutes")
}

func main() {
opt := mustGetOption()
taskr := tasker.New(opt)
mustParseOption()

taskr := tasker.New(opt)
for _, task := range tasker.MustParseTaskfile(opt) {
taskr.Task(task.Expr, taskr.Taskify(task.Cmd, opt))
}

if opt.Until > 0 {
taskr.Until(time.Duration(opt.Until) * time.Minute)
taskr.Until(time.Duration(opt.Until) * tick)
}

taskr.Run()
}

func mustGetOption() tasker.Option {
var opt tasker.Option

flag.StringVar(&opt.File, "file", "", "The task file in crontab format")
flag.StringVar(&opt.Tz, "tz", "Local", "The timezone to use for tasks")
flag.StringVar(&opt.Shell, "shell", tasker.Shell()[0], "The shell to use for running tasks")
flag.StringVar(&opt.Out, "out", "", "The fullpath to file where output from tasks are sent to")
flag.BoolVar(&opt.Verbose, "verbose", false, "The verbose mode outputs as much as possible")
flag.Int64Var(&opt.Until, "until", 0, "The timeout for task daemon in minutes")
func mustParseOption() {
opt = tasker.Option{}
flag.Parse()

if opt.File == "" {
flag.Usage()
os.Exit(1)
exit(1)
}

if _, err := os.Stat(opt.File); err != nil {
log.Fatalf("can't read taskfile: %s", opt.File)
log.Printf("can't read taskfile: %s", opt.File)
exit(1)
}

return opt
}
29 changes: 26 additions & 3 deletions cmd/tasker/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,45 @@ package main
import (
"os"
"testing"
"time"

"github.com/adhocore/gronx/pkg/tasker"
)

func TestMustGetOption(t *testing.T) {
old := os.Args
exit = func (code int) {}
t.Run("Main", func(t *testing.T) {
expect := tasker.Option{File: "../../test/taskfile.txt", Out: "../../test/out.txt"}
os.Args = append(os.Args, "-verbose", "-file", expect.File, "-out", expect.Out)
opt := mustGetOption()
os.Args = old
os.Args = append(old, "-verbose", "-file", expect.File, "-out", expect.Out)
mustParseOption()
if opt.File != expect.File {
t.Errorf("file: expected %v, got %v", opt.File, expect.File)
}
if opt.Out != expect.Out {
t.Errorf("out: expected %v, got %v", opt.Out, expect.Out)
}

t.Run("must parse option", func (t *testing.T) {
os.Args = append(old, "-verbose", "-out", expect.Out)
mustParseOption()
if opt.File != "" {
t.Error("opt.File must be empty "+opt.File)
}

os.Args = append(old, "-verbose", "-file", "invalid", "-out", expect.Out)
mustParseOption()
if opt.File != "invalid" {
t.Error("opt.File must be invalid")
}
})

t.Run("run", func (t *testing.T) {
tick = time.Second
os.Args = append(old, "-verbose", "-file", expect.File, "-out", expect.Out, "-until", "2")
main()
})

os.Args = old
})
}
10 changes: 5 additions & 5 deletions gronx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ func testcases() []Case {
{"0 0 * * 0,2-6", "2011-06-20 23:09:00", false, "2011-06-21 00:00"},
{"0 0 1 1 0", "2011-06-15 23:09:00", false, "2012-01-01 00:00"},
{"0 0 1 JAN 0", "2011-06-15 23:09:00", false, "2012-01-01 00:00"},
{"0 0 1 * 0", "2011-06-15 23:09:00", false, "2012-01-01 00:00"}, // 1
{"0 0 1 * 0", "2011-06-15 23:09:00", false, "2012-01-01 00:00"},
{"0 0 L * *", "2011-07-15 00:00:00", false, "2011-07-31 00:00"},
{"0 0 2W * *", "2011-07-01 00:00:00", true, "2011-08-02 00:00"},
{"0 0 1W * *", "2011-05-01 00:00:00", false, "2011-05-02 00:00"},
Expand All @@ -147,10 +147,10 @@ func testcases() []Case {
{"0 0 28W * *", "2011-07-01 00:00:00", false, "2011-07-28 00:00"},
{"0 0 30W * *", "2011-07-01 00:00:00", false, "2011-07-29 00:00"},
{"0 0 31W * *", "2011-07-01 00:00:00", false, "2011-07-29 00:00"},
{"* * * * * 2012", "2011-05-01 00:00:00", false, "err"},
{"* * * * * 2012", "2011-05-01 00:00:00", false, "2012-05-01 00:00"}, // 1
{"* * * * 5L", "2011-07-01 00:00:00", false, "2011-07-29 00:00"},
{"* * * * 6L", "2011-07-01 00:00:00", false, "2011-07-30 00:00"},
{"* * * * 7L", "2011-07-01 00:00:00", false, "2011-10-09 00:00"}, // 2
{"* * * * 7L", "2011-07-01 00:00:00", false, "2011-10-09 00:00"},
{"* * * * 1L", "2011-07-24 00:00:00", false, "2011-07-25 00:00"},
{"* * * * TUEL", "2011-07-24 00:00:00", false, "2011-07-26 00:00"},
{"* * * 1 5L", "2011-12-25 00:00:00", false, "2012-01-27 00:00"},
Expand All @@ -161,8 +161,8 @@ func testcases() []Case {
{"5/20 * * * *", "2018-08-13 00:24:00", false, "2018-08-13 00:25"},
{"5/20 * * * *", "2018-08-13 00:45:00", true, "2018-08-13 01:05"},
{"5-11/4 * * * *", "2018-08-13 00:03:00", false, "2018-08-13 00:05"},
{"0 0 L * 0", "2011-06-15 23:09:00", false, "2011-07-31 00:00"}, // 3
{"3-59/15 6-12 */15 1 2-5", "2017-01-08 00:00:00", false, "2018-01-30 06:03"}, // 4
{"0 0 L * 0", "2011-06-15 23:09:00", false, "2011-07-31 00:00"},
{"3-59/15 6-12 */15 1 2-5", "2017-01-08 00:00:00", false, "2018-01-30 06:03"},
{"* * * * MON-FRI", "2017-01-08 00:00:00", false, "2017-01-09 00:00"},
{"* * * * TUE", "2017-01-08 00:00:00", false, "2017-01-10 00:00"},
{"0 1 15 JUL mon,Wed,FRi", "2019-11-14 00:00:00", false, "2020-07-15 01:00"},
Expand Down
13 changes: 10 additions & 3 deletions next.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package gronx
import (
"errors"
"fmt"
"regexp"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -61,18 +62,24 @@ func loop(gron Gronx, segments []string, start time.Time, incl bool) (next time.
return start, errors.New("tried so hard")
}

var dashRe = regexp.MustCompile(`/.*$`)

func isPastYear(year string, ref time.Time, incl bool) bool {
if year == "*" || year == "?" {
return false
}

min := ref.Year()
if !incl {
min++
}
for _, offset := range strings.Split(year, ",") {
if strings.Contains(offset, "/") && strings.Index(offset, "*/") != 0 && strings.Index(offset, "0/") != 0 {
if strings.Index(offset, "*/") == 0 || strings.Index(offset, "0/") == 0 {
return false
}
for _, part := range strings.Split(offset, "-") {
for _, part := range strings.Split(dashRe.ReplaceAllString(offset, ""), "-") {
val, err := strconv.Atoi(part)
if err != nil || val > min {
if err != nil || val >= min {
return false
}
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/tasker/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
func TestMustParseTaskfile(t *testing.T) {
t.Run("MustParseTaskfile", func(t *testing.T) {
tasks := MustParseTaskfile(Option{File: "../../test/taskfile.txt"})
if len(tasks) != 6 {
t.Errorf("should have 6 tasks, got %d", len(tasks))
if len(tasks) != 8 {
t.Errorf("should have 8 tasks, got %d", len(tasks))
}

if tasks[0].Expr != "*/1 0/1 * * *" {
Expand Down
4 changes: 4 additions & 0 deletions test/taskfile.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
* * * * * echo '[task 5] * * * * *' > test/task5.out
* * * * * echo '[task 6] it should go to outfile' && invalid-cmd

# failure tasks
@always xgronx
@always false

# below are invalid
@invalid
* * * * *

0 comments on commit 1c36643

Please sign in to comment.