aboutsummaryrefslogtreecommitdiff
path: root/internal/yaml
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--internal/yaml/yaml.go138
-rw-r--r--pkg/config/yaml_test.go (renamed from internal/yaml/yaml_test.go)143
2 files changed, 77 insertions, 204 deletions
diff --git a/internal/yaml/yaml.go b/internal/yaml/yaml.go
deleted file mode 100644
index 23a38ef..0000000
--- a/internal/yaml/yaml.go
+++ /dev/null
@@ -1,138 +0,0 @@
-package yaml
-
-import (
- "fmt"
- "io/ioutil"
-
- "gopkg.in/yaml.v3"
-
- C "github.com/Necoro/feed2imap-go/internal/config"
- F "github.com/Necoro/feed2imap-go/internal/feed"
- "github.com/Necoro/feed2imap-go/internal/log"
-)
-
-type config struct {
- C.GlobalOptions `yaml:",inline"`
- GlobalConfig C.Map `yaml:",inline"`
- Feeds []configGroupFeed
-}
-
-type group struct {
- Group string
- Feeds []configGroupFeed
-}
-
-type feed struct {
- Name string
- Url string
- C.Options `yaml:",inline"`
-}
-
-type configGroupFeed struct {
- Target *string
- Feed feed `yaml:",inline"`
- Group group `yaml:",inline"`
-}
-
-func (grpFeed *configGroupFeed) isGroup() bool {
- return grpFeed.Group.Group != ""
-}
-
-func (grpFeed *configGroupFeed) isFeed() bool {
- return grpFeed.Feed.Name != "" || grpFeed.Feed.Url != ""
-}
-
-func (grpFeed *configGroupFeed) target() string {
- if grpFeed.Target != nil {
- return *grpFeed.Target
- }
- if grpFeed.Feed.Name != "" {
- return grpFeed.Feed.Name
- }
-
- return grpFeed.Group.Group
-}
-
-func parse(buf []byte) (config, error) {
- parsedCfg := config{GlobalOptions: C.DefaultGlobalOptions}
-
- if err := yaml.Unmarshal(buf, &parsedCfg); err != nil {
- return config{}, fmt.Errorf("while unmarshalling: %w", err)
- }
- //fmt.Printf("--- parsedCfg:\n%+v\n\n", parsedCfg)
-
- return parsedCfg, nil
-}
-
-func appTarget(target []string, app string) []string {
- switch {
- case len(target) == 0 && app == "":
- return []string{}
- case len(target) == 0:
- return []string{app}
- case app == "":
- return target
- default:
- return append(target, app)
- }
-}
-
-// Parse the group structure and populate the `Target` fields in the feeds
-func buildFeeds(cfg []configGroupFeed, target []string, feeds *F.Feeds) error {
- for idx := range cfg {
- f := &cfg[idx] // cannot use `_, f := range cfg` as it returns copies(!), but we need the originals
- target := appTarget(target, f.target())
- switch {
- case f.isFeed() && f.isGroup():
- return fmt.Errorf("Entry with Target %s is both a Feed and a group", target)
-
- case f.isFeed():
- name := f.Feed.Name
- if name == "" {
- return fmt.Errorf("Unnamed feed")
- }
-
- if feeds.Contains(name) {
- return fmt.Errorf("Duplicate Feed Name '%s'", name)
- }
- feeds.Set(name, &F.Feed{
- Name: f.Feed.Name,
- Target: target,
- Url: f.Feed.Url,
- Options: f.Feed.Options,
- })
-
- case f.isGroup():
- if err := buildFeeds(f.Group.Feeds, target, feeds); err != nil {
- return err
- }
- }
- }
-
- return nil
-}
-
-func Load(path string) (*C.Config, *F.Feeds, error) {
- log.Printf("Reading configuration file '%s'", path)
-
- buf, err := ioutil.ReadFile(path)
- if err != nil {
- return nil, nil, fmt.Errorf("while reading '%s': %w", path, err)
- }
-
- var parsedCfg config
- if parsedCfg, err = parse(buf); err != nil {
- return nil, nil, err
- }
-
- feeds := F.NewFeeds()
-
- if err := buildFeeds(parsedCfg.Feeds, []string{}, feeds); err != nil {
- return nil, nil, fmt.Errorf("while parsing: %w", err)
- }
-
- return &C.Config{
- GlobalOptions: parsedCfg.GlobalOptions,
- GlobalConfig: parsedCfg.GlobalConfig,
- }, feeds, nil
-}
diff --git a/internal/yaml/yaml_test.go b/pkg/config/yaml_test.go
index 9562ef8..501ead3 100644
--- a/internal/yaml/yaml_test.go
+++ b/pkg/config/yaml_test.go
@@ -1,14 +1,14 @@
-package yaml
+package config
import (
"reflect"
"strings"
"testing"
- C "github.com/Necoro/feed2imap-go/internal/config"
- F "github.com/Necoro/feed2imap-go/internal/feed"
+ "github.com/davecgh/go-spew/spew"
)
+func i(i int) *int { return &i }
func s(s string) *string { return &s }
func b(b bool) *bool { return &b }
func t(s string) []string {
@@ -24,121 +24,125 @@ func TestBuildFeeds(tst *testing.T) {
wantErr bool
target string
feeds []configGroupFeed
- result F.Feeds
+ result Feeds
}{
- {name: "Empty input", wantErr: false, target: "", feeds: nil, result: F.Feeds{}},
+ {name: "Empty input", wantErr: false, target: "", feeds: nil, result: Feeds{}},
{name: "Empty Feed", wantErr: true, target: "",
feeds: []configGroupFeed{
- {Target: s("foo"), Feed: feed{Url: "google.de"}},
- }, result: F.Feeds{}},
+ {Target: s("foo"), Feed: Feed{Url: "google.de"}},
+ }, result: Feeds{}},
{name: "Empty Feed", wantErr: true, target: "",
feeds: []configGroupFeed{
- {Target: nil, Feed: feed{Url: "google.de"}},
- }, result: F.Feeds{}},
+ {Target: nil, Feed: Feed{Url: "google.de"}},
+ }, result: Feeds{}},
{name: "Duplicate Feed Name", wantErr: true, target: "",
feeds: []configGroupFeed{
- {Target: nil, Feed: feed{Name: "Dup"}},
- {Target: nil, Feed: feed{Name: "Dup"}},
- }, result: F.Feeds{}},
+ {Target: nil, Feed: Feed{Name: "Dup"}},
+ {Target: nil, Feed: Feed{Name: "Dup"}},
+ }, result: Feeds{}},
{name: "Simple", wantErr: false, target: "",
feeds: []configGroupFeed{
- {Target: s("foo"), Feed: feed{Name: "muh"}},
+ {Target: s("foo"), Feed: Feed{Name: "muh"}},
},
- result: F.Feeds{"muh": &F.Feed{Name: "muh", Target: t("foo")}},
+ result: Feeds{"muh": Feed{Name: "muh", Target: t("foo")}},
},
{name: "Simple With Target", wantErr: false, target: "moep",
feeds: []configGroupFeed{
- {Target: s("foo"), Feed: feed{Name: "muh"}},
+ {Target: s("foo"), Feed: Feed{Name: "muh"}},
},
- result: F.Feeds{"muh": &F.Feed{Name: "muh", Target: t("moep.foo")}},
+ result: Feeds{"muh": Feed{Name: "muh", Target: t("moep.foo")}},
},
{name: "Simple With Nil Target", wantErr: false, target: "moep",
feeds: []configGroupFeed{
- {Target: nil, Feed: feed{Name: "muh"}},
+ {Target: nil, Feed: Feed{Name: "muh"}},
},
- result: F.Feeds{"muh": &F.Feed{Name: "muh", Target: t("moep.muh")}},
+ result: Feeds{"muh": Feed{Name: "muh", Target: t("moep.muh")}},
},
{name: "Simple With Empty Target", wantErr: false, target: "moep",
feeds: []configGroupFeed{
- {Target: s(""), Feed: feed{Name: "muh"}},
+ {Target: s(""), Feed: Feed{Name: "muh"}},
},
- result: F.Feeds{"muh": &F.Feed{Name: "muh", Target: t("moep")}},
+ result: Feeds{"muh": Feed{Name: "muh", Target: t("moep")}},
},
{name: "Multiple Feeds", wantErr: false, target: "moep",
feeds: []configGroupFeed{
- {Target: s("foo"), Feed: feed{Name: "muh"}},
- {Target: nil, Feed: feed{Name: "bar"}},
+ {Target: s("foo"), Feed: Feed{Name: "muh"}},
+ {Target: nil, Feed: Feed{Name: "bar"}},
},
- result: F.Feeds{
- "muh": &F.Feed{Name: "muh", Target: t("moep.foo")},
- "bar": &F.Feed{Name: "bar", Target: t("moep.bar")},
+ result: Feeds{
+ "muh": Feed{Name: "muh", Target: t("moep.foo")},
+ "bar": Feed{Name: "bar", Target: t("moep.bar")},
},
},
{name: "Empty Group", wantErr: false, target: "",
feeds: []configGroupFeed{
{Target: nil, Group: group{Group: "G1"}},
},
- result: F.Feeds{},
+ result: Feeds{},
},
{name: "Simple Group", wantErr: false, target: "",
feeds: []configGroupFeed{
{Target: nil, Group: group{Group: "G1", Feeds: []configGroupFeed{
- {Target: s("bar"), Feed: feed{Name: "F1"}},
- {Target: s(""), Feed: feed{Name: "F2"}},
- {Target: nil, Feed: feed{Name: "F3"}},
+ {Target: s("bar"), Feed: Feed{Name: "F1"}},
+ {Target: s(""), Feed: Feed{Name: "F2"}},
+ {Target: nil, Feed: Feed{Name: "F3"}},
}}},
},
- result: F.Feeds{
- "F1": &F.Feed{Name: "F1", Target: t("G1.bar")},
- "F2": &F.Feed{Name: "F2", Target: t("G1")},
- "F3": &F.Feed{Name: "F3", Target: t("G1.F3")},
+ result: Feeds{
+ "F1": Feed{Name: "F1", Target: t("G1.bar")},
+ "F2": Feed{Name: "F2", Target: t("G1")},
+ "F3": Feed{Name: "F3", Target: t("G1.F3")},
},
},
{name: "Nested Groups", wantErr: false, target: "",
feeds: []configGroupFeed{
{Target: nil, Group: group{Group: "G1", Feeds: []configGroupFeed{
- {Target: nil, Feed: feed{Name: "F0"}},
+ {Target: nil, Feed: Feed{Name: "F0"}},
{Target: s("bar"), Group: group{Group: "G2",
- Feeds: []configGroupFeed{{Target: nil, Feed: feed{Name: "F1"}}}}},
+ Feeds: []configGroupFeed{{Target: nil, Feed: Feed{Name: "F1"}}}}},
{Target: s(""), Group: group{Group: "G3",
- Feeds: []configGroupFeed{{Target: s("baz"), Feed: feed{Name: "F2"}}}}},
+ Feeds: []configGroupFeed{{Target: s("baz"), Feed: Feed{Name: "F2"}}}}},
{Target: nil, Group: group{Group: "G4",
- Feeds: []configGroupFeed{{Target: nil, Feed: feed{Name: "F3"}}}}},
+ Feeds: []configGroupFeed{{Target: nil, Feed: Feed{Name: "F3"}}}}},
}}},
},
- result: F.Feeds{
- "F0": &F.Feed{Name: "F0", Target: t("G1.F0")},
- "F1": &F.Feed{Name: "F1", Target: t("G1.bar.F1")},
- "F2": &F.Feed{Name: "F2", Target: t("G1.baz")},
- "F3": &F.Feed{Name: "F3", Target: t("G1.G4.F3")},
+ result: Feeds{
+ "F0": Feed{Name: "F0", Target: t("G1.F0")},
+ "F1": Feed{Name: "F1", Target: t("G1.bar.F1")},
+ "F2": Feed{Name: "F2", Target: t("G1.baz")},
+ "F3": Feed{Name: "F3", Target: t("G1.G4.F3")},
},
},
}
for _, tt := range tests {
tst.Run(tt.name, func(tst *testing.T) {
- var feeds = F.Feeds{}
+ var feeds = Feeds{}
err := buildFeeds(tt.feeds, t(tt.target), feeds)
if (err != nil) != tt.wantErr {
tst.Errorf("buildFeeds() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr && !reflect.DeepEqual(feeds, tt.result) {
- tst.Errorf("buildFeeds() got = %v, want %v", feeds, tt.result)
+ tst.Errorf("buildFeeds() got: %s\nwant: %s", spew.Sdump(feeds), spew.Sdump(tt.result))
}
})
}
}
-func defaultConfig(feeds []configGroupFeed, global C.Map) config {
+func defaultConfig(feeds []configGroupFeed, global Map) config {
+ defCfg := WithDefault()
+ if global != nil {
+ defCfg.GlobalConfig = global
+ }
return config{
- GlobalOptions: C.DefaultGlobalOptions,
- GlobalConfig: global,
- Feeds: feeds,
+ Config: defCfg,
+ Feeds: feeds,
+ GlobalConfig: global,
}
}
//noinspection GoNilness,GoNilness
-func TestParse(tst *testing.T) {
+func TestUnmarshal(tst *testing.T) {
tests := []struct {
name string
inp string
@@ -149,14 +153,21 @@ func TestParse(tst *testing.T) {
inp: "", wantErr: false, config: defaultConfig(nil, nil)},
{name: "Trash", inp: "Something", wantErr: true},
{name: "Simple config",
- inp: "something: 1\nsomething_else: 2", wantErr: false, config: defaultConfig(nil, C.Map{"something": 1, "something_else": 2})},
+ inp: "something: 1\nsomething_else: 2", wantErr: false, config: defaultConfig(nil, Map{"something": 1, "something_else": 2})},
{name: "Known config",
inp: "whatever: 2\ndefault-email: foo@foobar.de\ntimeout: 60\nsomething: 1", wantErr: false, config: func() config {
- c := defaultConfig(nil, C.Map{"something": 1, "whatever": 2})
+ c := defaultConfig(nil, Map{"something": 1, "whatever": 2})
c.Timeout = 60
c.DefaultEmail = "foo@foobar.de"
return c
}()},
+ {name: "Known config with feed-options",
+ inp: "whatever: 2\ntimeout: 60\noptions:\n min-frequency: 6", wantErr: false, config: func() config {
+ c := defaultConfig(nil, Map{"whatever": 2})
+ c.Timeout = 60
+ c.FeedOptions.MinFreq = i(6)
+ return c
+ }()},
{name: "Config with feed",
inp: `
something: 1
@@ -169,14 +180,14 @@ feeds:
`,
wantErr: false,
config: defaultConfig([]configGroupFeed{
- {Target: s("bar"), Feed: feed{
+ {Target: s("bar"), Feed: Feed{
Name: "Foo",
Url: "whatever",
- Options: C.Options{
- MinFreq: 0,
+ Options: Options{
+ MinFreq: nil,
InclImages: b(true),
},
- }}}, C.Map{"something": 1})},
+ }}}, Map{"something": 1})},
{name: "Feeds",
inp: `
@@ -191,19 +202,19 @@ feeds:
`,
wantErr: false,
config: defaultConfig([]configGroupFeed{
- {Target: nil, Feed: feed{
+ {Target: nil, Feed: Feed{
Name: "Foo",
Url: "whatever",
- Options: C.Options{
- MinFreq: 2,
+ Options: Options{
+ MinFreq: i(2),
InclImages: nil,
},
}},
- {Target: s("bla"), Feed: feed{
+ {Target: s("bla"), Feed: Feed{
Name: "Shrubbery",
Url: "google.de",
- Options: C.Options{
- MinFreq: 0,
+ Options: Options{
+ MinFreq: nil,
InclImages: b(false),
},
}},
@@ -236,7 +247,7 @@ feeds:
`,
wantErr: false,
config: defaultConfig([]configGroupFeed{
- {Target: nil, Feed: feed{
+ {Target: nil, Feed: Feed{
Name: "Foo",
Url: "whatever",
}},
@@ -246,10 +257,10 @@ feeds:
{Target: s(""), Group: group{
Group: "G2",
Feeds: []configGroupFeed{
- {Target: nil, Feed: feed{Name: "F1", Url: "google.de"}},
+ {Target: nil, Feed: Feed{Name: "F1", Url: "google.de"}},
}},
},
- {Target: nil, Feed: feed{Name: "F2"}},
+ {Target: nil, Feed: Feed{Name: "F2"}},
{Target: nil, Group: group{Group: "G3"}},
}},
},
@@ -260,13 +271,13 @@ feeds:
for _, tt := range tests {
tst.Run(tt.name, func(tst *testing.T) {
var buf = []byte(tt.inp)
- got, err := parse(buf)
+ got, err := unmarshal(buf, WithDefault())
if (err != nil) != tt.wantErr {
tst.Errorf("parse() error = %v, wantErr %v", err, tt.wantErr)
return
}
if err == nil && !reflect.DeepEqual(got, tt.config) {
- tst.Errorf("parse() got = %#v, want %#v", got, tt.config)
+ tst.Errorf("parse() got: %s\nwant: %s", spew.Sdump(got), spew.Sdump(tt.config))
}
})
}