This commit is contained in:
Erik Winter 2024-12-19 12:06:03 +01:00
parent caa1a45efb
commit 55fe158f79
3 changed files with 110 additions and 114 deletions

View File

@ -1,109 +1,68 @@
package command_test
// func TestArgSet(t *testing.T) {
// t.Parallel()
import (
"testing"
// as := command.ArgSet{
// Main: "main",
// Flags: map[string]string{
// "name 1": "value 1",
// "name 2": "value 2",
// "name 3": "value 3",
// },
// }
"github.com/google/go-cmp/cmp"
"go-mod.ewintr.nl/planner/plan/command"
)
// t.Run("hasflag", func(t *testing.T) {
// t.Run("true", func(t *testing.T) {
// if has := as.HasFlag("name 1"); !has {
// t.Errorf("exp true, got %v", has)
// }
// })
// t.Run("false", func(t *testing.T) {
// if has := as.HasFlag("unknown"); has {
// t.Errorf("exp false, got %v", has)
// }
// })
// })
func TestParseArgs(t *testing.T) {
t.Parallel()
// t.Run("flag", func(t *testing.T) {
// t.Run("known", func(t *testing.T) {
// if val := as.Flag("name 1"); val != "value 1" {
// t.Errorf("exp value 1, got %v", val)
// }
// })
// t.Run("unknown", func(t *testing.T) {
// if val := as.Flag("unknown"); val != "" {
// t.Errorf(`exp "", got %v`, val)
// }
// })
// })
// t.Run("setflag", func(t *testing.T) {
// exp := "new value"
// as.SetFlag("new name", exp)
// if act := as.Flag("new name"); exp != act {
// t.Errorf("exp %v, got %v", exp, act)
// }
// })
// }
// func TestParseArgs(t *testing.T) {
// t.Parallel()
// for _, tc := range []struct {
// name string
// args []string
// expAS *command.ArgSet
// expErr bool
// }{
// {
// name: "empty",
// expAS: &command.ArgSet{
// Flags: map[string]string{},
// },
// },
// {
// name: "just main",
// args: []string{"one", "two three", "four"},
// expAS: &command.ArgSet{
// Main: "one two three four",
// Flags: map[string]string{},
// },
// },
// {
// name: "with flags",
// args: []string{"-flag1", "value1", "one", "two", "-flag2", "value2", "-flag3", "value3"},
// expAS: &command.ArgSet{
// Main: "one two",
// Flags: map[string]string{
// "flag1": "value1",
// "flag2": "value2",
// "flag3": "value3",
// },
// },
// },
// {
// name: "flag without value",
// args: []string{"one", "two", "-flag1"},
// expErr: true,
// },
// {
// name: "split main",
// args: []string{"one", "-flag1", "value1", "two"},
// expErr: true,
// },
// } {
// t.Run(tc.name, func(t *testing.T) {
// actAS, actErr := command.ParseArgs(tc.args)
// if tc.expErr != (actErr != nil) {
// t.Errorf("exp %v, got %v", tc.expErr, actErr)
// }
// if tc.expErr {
// return
// }
// if diff := cmp.Diff(tc.expAS, actAS); diff != "" {
// t.Errorf("(exp +, got -)\n%s", diff)
// }
// })
// }
// }
for _, tc := range []struct {
name string
args []string
expMain []string
expFlags map[string]string
expErr bool
}{
{
name: "empty",
expMain: []string{},
expFlags: map[string]string{},
},
{
name: "just main",
args: []string{"one", "two three", "four"},
expMain: []string{"one", "two three", "four"},
expFlags: map[string]string{},
},
{
name: "with flags",
args: []string{"-flag1", "value1", "one", "two", "-flag2", "value2", "-flag3", "value3"},
expMain: []string{"one", "two"},
expFlags: map[string]string{
"flag1": "value1",
"flag2": "value2",
"flag3": "value3",
},
},
{
name: "flag without value",
args: []string{"one", "two", "-flag1"},
expErr: true,
},
{
name: "split main",
args: []string{"one", "-flag1", "value1", "two"},
expErr: true,
},
} {
t.Run(tc.name, func(t *testing.T) {
actMain, actFlags, actErr := command.ParseFlags(tc.args)
if tc.expErr != (actErr != nil) {
t.Errorf("exp %v, got %v", tc.expErr, actErr)
}
if tc.expErr {
return
}
if diff := cmp.Diff(tc.expMain, actMain); diff != "" {
t.Errorf("(exp +, got -)\n%s", diff)
}
if diff := cmp.Diff(tc.expFlags, actFlags); diff != "" {
t.Errorf("(exp +, got -)\n%s", diff)
}
})
}
}

View File

@ -2,6 +2,7 @@ package sqlite
import (
"database/sql"
"encoding/json"
"fmt"
"time"
@ -14,18 +15,29 @@ type SqliteEvent struct {
}
func (s *SqliteEvent) Store(event item.Event) error {
var recurStr *string
if event.Recurrer != nil {
recurBytes, err := json.Marshal(event.Recurrer)
if err != nil {
return fmt.Errorf("could not marshal recurrer: %v", err)
}
rs := string(recurBytes)
recurStr = &rs
}
if _, err := s.db.Exec(`
INSERT INTO events
(id, title, start, duration)
(id, title, start, duration, recur)
VALUES
(?, ?, ?, ?)
(?, ?, ?, ?, ?)
ON CONFLICT(id) DO UPDATE
SET
title=?,
start=?,
duration=?`,
event.ID, event.Title, event.Start.Format(timestampFormat), event.Duration.String(),
event.Title, event.Start.Format(timestampFormat), event.Duration.String()); err != nil {
duration=?,
recur=?
`,
event.ID, event.Title, event.Start.Format(timestampFormat), event.Duration.String(), recurStr,
event.Title, event.Start.Format(timestampFormat), event.Duration.String(), recurStr); err != nil {
return fmt.Errorf("%w: %v", ErrSqliteFailure, err)
}
return nil
@ -34,10 +46,11 @@ duration=?`,
func (s *SqliteEvent) Find(id string) (item.Event, error) {
var event item.Event
var durStr string
var recurStr *string
err := s.db.QueryRow(`
SELECT id, title, start, duration
SELECT id, title, start, duration, recur
FROM events
WHERE id = ?`, id).Scan(&event.ID, &event.Title, &event.Start, &durStr)
WHERE id = ?`, id).Scan(&event.ID, &event.Title, &event.Start, &durStr, &recurStr)
switch {
case err == sql.ErrNoRows:
return item.Event{}, fmt.Errorf("event not found: %w", err)
@ -46,16 +59,23 @@ WHERE id = ?`, id).Scan(&event.ID, &event.Title, &event.Start, &durStr)
}
dur, err := time.ParseDuration(durStr)
if err != nil {
return item.Event{}, fmt.Errorf("%w: %v", ErrSqliteFailure, err)
return item.Event{}, fmt.Errorf("could not unmarshal recurrer: %v", err)
}
event.Duration = dur
if recurStr != nil {
var rec item.Recur
if err := json.Unmarshal([]byte(*recurStr), &rec); err != nil {
return item.Event{}, fmt.Errorf("%w: %v", ErrSqliteFailure, err)
}
event.Recurrer = &rec
}
return event, nil
}
func (s *SqliteEvent) FindAll() ([]item.Event, error) {
rows, err := s.db.Query(`
SELECT id, title, start, duration
SELECT id, title, start, duration, recur
FROM events`)
if err != nil {
return nil, fmt.Errorf("%w: %v", ErrSqliteFailure, err)
@ -65,7 +85,8 @@ FROM events`)
for rows.Next() {
var event item.Event
var durStr string
if err := rows.Scan(&event.ID, &event.Title, &event.Start, &durStr); err != nil {
var recurStr *string
if err := rows.Scan(&event.ID, &event.Title, &event.Start, &durStr, &recurStr); err != nil {
return nil, fmt.Errorf("%w: %v", ErrSqliteFailure, err)
}
dur, err := time.ParseDuration(durStr)
@ -73,6 +94,13 @@ FROM events`)
return nil, fmt.Errorf("%w: %v", ErrSqliteFailure, err)
}
event.Duration = dur
if recurStr != nil {
var rec item.Recur
if err := json.Unmarshal([]byte(*recurStr), &rec); err != nil {
return nil, fmt.Errorf("could not unmarshal recurrer: %v", err)
}
event.Recurrer = &rec
}
result = append(result, event)
}

View File

@ -25,6 +25,15 @@ var migrations = []string{
deleted BOOLEAN NOT NULL,
body TEXT NOT NULL
)`,
`ALTER TABLE events ADD COLUMN recur_period TEXT`,
`ALTER TABLE events ADD COLUMN recur_count INTEGER`,
`ALTER TABLE events ADD COLUMN recur_start TIMESTAMP`,
`ALTER TABLE events ADD COLUMN recur_next TIMESTAMP`,
`ALTER TABLE events DROP COLUMN recur_period`,
`ALTER TABLE events DROP COLUMN recur_count`,
`ALTER TABLE events DROP COLUMN recur_start`,
`ALTER TABLE events DROP COLUMN recur_next`,
`ALTER TABLE events ADD COLUMN recur TEXT`,
}
var (