Compare commits
3 commits
aa5ea0ad70
...
d34363b8c0
| Author | SHA1 | Date | |
|---|---|---|---|
| d34363b8c0 | |||
| 01d6dd9b0b | |||
| c1bd35fe9e |
6 changed files with 347 additions and 70 deletions
|
|
@ -1,5 +1,10 @@
|
|||
# Changelog
|
||||
|
||||
## [0.2.0] - 2026-03-07
|
||||
|
||||
- Add ID field to Entry struct with auto-generation on marshal/unmarshal
|
||||
- Upgrade mapstructure to maintained fork
|
||||
|
||||
## [0.1.1] - 2026-03-01
|
||||
|
||||
- Add Time method to Date struct for accessing internal timestamp
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import (
|
|||
"codeberg.org/danjones000/my-log/tools"
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/caarlos0/env/v10"
|
||||
mapst "github.com/mitchellh/mapstructure"
|
||||
mapst "github.com/go-viper/mapstructure/v2"
|
||||
)
|
||||
|
||||
var ConfigPath string
|
||||
|
|
|
|||
2
go.mod
2
go.mod
|
|
@ -5,9 +5,9 @@ go 1.26.0
|
|||
require (
|
||||
github.com/BurntSushi/toml v1.3.2
|
||||
github.com/caarlos0/env/v10 v10.0.0
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/markusmobius/go-dateparser v1.2.3
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/nalgeon/be v0.3.0
|
||||
github.com/spf13/cobra v1.8.0
|
||||
)
|
||||
|
|
|
|||
4
go.sum
4
go.sum
|
|
@ -7,6 +7,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/elliotchance/pie/v2 v2.7.0 h1:FqoIKg4uj0G/CrLGuMS9ejnFKa92lxE1dEgBD3pShXg=
|
||||
github.com/elliotchance/pie/v2 v2.7.0/go.mod h1:18t0dgGFH006g4eVdDtWfgFZPQEgl10IoEO8YWEq3Og=
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hablullah/go-hijri v1.0.2 h1:drT/MZpSZJQXo7jftf5fthArShcaMtsal0Zf/dnmp6k=
|
||||
|
|
@ -21,8 +23,6 @@ github.com/magefile/mage v1.14.0 h1:6QDX3g6z1YvJ4olPhT1wksUcSa/V0a1B+pJb73fBjyo=
|
|||
github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
|
||||
github.com/markusmobius/go-dateparser v1.2.3 h1:TvrsIvr5uk+3v6poDjaicnAFJ5IgtFHgLiuMY2Eb7Nw=
|
||||
github.com/markusmobius/go-dateparser v1.2.3/go.mod h1:cMwQRrBUQlK1UI5TIFHEcvpsMbkWrQLXuaPNMFzuYLk=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/nalgeon/be v0.3.0 h1:QsPANqEtcOD5qT2S3KAtIkDBBn8SXUf/Lb5Bi/z4UqM=
|
||||
github.com/nalgeon/be v0.3.0/go.mod h1:PMwMuBLopwKJkSHnr2qHyLcZYUTqNejN7A8RAqNWO3E=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
|
|
|
|||
|
|
@ -20,18 +20,47 @@ import (
|
|||
const DateFormat = tools.DateFormat
|
||||
|
||||
type Entry struct {
|
||||
// ID is an optional, but recommended field.
|
||||
// When marshaling/unmarshaling, if ID is empty, one is generated.
|
||||
ID string
|
||||
Title string
|
||||
Date time.Time
|
||||
Fields Metas
|
||||
}
|
||||
|
||||
func GenerateID() string {
|
||||
host, hostErr := os.Hostname()
|
||||
if hostErr != nil {
|
||||
host = "localhost"
|
||||
}
|
||||
return fmt.Sprintf(
|
||||
"tag:%s,%s:my-log/%s",
|
||||
host,
|
||||
time.Now().Local().Format("2006"),
|
||||
uuid.NewString(),
|
||||
)
|
||||
}
|
||||
|
||||
func EnsureID(id *string, fields Metas) {
|
||||
if *id != "" {
|
||||
return
|
||||
}
|
||||
|
||||
metaID, hasMetaID := fields.Get("id")
|
||||
var isStringID bool
|
||||
*id, isStringID = metaID.(string)
|
||||
if !hasMetaID || !isStringID {
|
||||
*id = GenerateID()
|
||||
}
|
||||
}
|
||||
|
||||
type metaRes struct {
|
||||
out []byte
|
||||
err error
|
||||
}
|
||||
|
||||
func (e Entry) getFieldMarshalChan() chan metaRes {
|
||||
size := len(e.Fields)
|
||||
func getFieldMarshalChan(fields Metas) chan metaRes {
|
||||
size := len(fields)
|
||||
ch := make(chan metaRes, size)
|
||||
var wg sync.WaitGroup
|
||||
|
||||
|
|
@ -53,7 +82,7 @@ func (e Entry) getFieldMarshalChan() chan metaRes {
|
|||
ch <- metaRes{o, er}
|
||||
}
|
||||
|
||||
}(e.Fields[i])
|
||||
}(fields[i])
|
||||
}
|
||||
|
||||
go func() {
|
||||
|
|
@ -71,16 +100,10 @@ func (e Entry) MarshalText() ([]byte, error) {
|
|||
if e.Date.IsZero() {
|
||||
return []byte{}, ErrorMissingDate
|
||||
}
|
||||
EnsureID(&e.ID, e.Fields)
|
||||
fields := e.Fields.Set("id", e.ID)
|
||||
|
||||
if _, hasId := e.Fields.Get("id"); !hasId {
|
||||
host, hostErr := os.Hostname()
|
||||
if hostErr != nil {
|
||||
host = "localhost"
|
||||
}
|
||||
e.Fields = e.Fields.Set("id", fmt.Sprintf("tag:%s,%s:my-log/%s", host, time.Now().Format("2006"), uuid.NewString()))
|
||||
}
|
||||
|
||||
ch := e.getFieldMarshalChan()
|
||||
ch := getFieldMarshalChan(fields)
|
||||
buff := &bytes.Buffer{}
|
||||
buff.WriteString("@begin ")
|
||||
buff.WriteString(e.Date.Format(DateFormat))
|
||||
|
|
@ -124,8 +147,14 @@ func (m *Entry) UnmarshalText(in []byte) error {
|
|||
m.Date = d
|
||||
|
||||
for meta := range ch {
|
||||
if meta.Key == "id" {
|
||||
if id, idIsString := meta.Value.(string); idIsString {
|
||||
m.ID = id
|
||||
}
|
||||
}
|
||||
m.Fields = append(m.Fields, meta)
|
||||
}
|
||||
EnsureID(&m.ID, m.Fields)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -195,11 +224,13 @@ func (e Entry) MarshalJSON() ([]byte, error) {
|
|||
if e.Date == (time.Time{}) {
|
||||
return []byte{}, ErrorMissingDate
|
||||
}
|
||||
EnsureID(&e.ID, e.Fields)
|
||||
fields := e.Fields.Set("id", e.ID)
|
||||
|
||||
out := map[string]any{}
|
||||
out["title"] = e.Title
|
||||
out["date"] = e.Date.Format(time.RFC3339)
|
||||
maps.Copy(out, e.Fields.Map())
|
||||
maps.Copy(out, fields.Map())
|
||||
return json.Marshal(out)
|
||||
}
|
||||
|
||||
|
|
@ -281,5 +312,6 @@ func (e *Entry) UnmarshalJSON(in []byte) error {
|
|||
}
|
||||
e.Fields = append(e.Fields, m)
|
||||
}
|
||||
EnsureID(&e.ID, e.Fields)
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"codeberg.org/danjones000/my-log/internal/testutil/bep"
|
||||
"github.com/nalgeon/be"
|
||||
)
|
||||
|
||||
|
|
@ -126,7 +125,7 @@ func TestEntryMarshal(t *testing.T) {
|
|||
|
||||
func getEntryMarshalTestRunner(title string, date time.Time, fields []Meta, first string, lines []string, err error) func(*testing.T) {
|
||||
return func(t *testing.T) {
|
||||
en := Entry{title, date, fields}
|
||||
en := Entry{Title: title, Date: date, Fields: fields}
|
||||
o, er := en.MarshalText()
|
||||
be.Err(t, er, err)
|
||||
if first == "" {
|
||||
|
|
@ -154,22 +153,24 @@ func TestEntryUnmarshal(t *testing.T) {
|
|||
in string
|
||||
title string
|
||||
date time.Time
|
||||
id string
|
||||
fields []Meta
|
||||
err error
|
||||
}{
|
||||
{"one-line", "@begin " + whens + " - A Title @end", "A Title", when, simple, nil},
|
||||
{"rfc3999-date", "@begin " + when.Format(time.RFC3339) + " - A Title @end", "A Title", when, simple, nil},
|
||||
{"multi-title", "@begin " + whens + " - A Title\nwith break @end", "A Title\nwith break", when, simple, nil},
|
||||
{"no-title", "@begin " + whens + " - @end", "", when, simple, ErrorMissingTitle},
|
||||
{"parse-error", "this is no good", "", when, simple, ErrorParsing},
|
||||
{"no-date", "@begin - A Title @end", "A Title", when, simple, ErrorMissingDate},
|
||||
{"bad-date", "@begin not-a-real date - A Title @end", "A Title", when, simple, ErrorParsing},
|
||||
{"one-field", "@begin " + whens + " - A Title\n@age 41 @end", "A Title", when, []Meta{{"age", 41}}, nil},
|
||||
{"one-line", "@begin " + whens + " - A Title @end", "A Title", when, "", simple, nil},
|
||||
{"with-id", "@begin " + whens + " - A Title\n@id jimmy-john @end", "A Title", when, "jimmy-john", simple, nil},
|
||||
{"rfc3999-date", "@begin " + when.Format(time.RFC3339) + " - A Title @end", "A Title", when, "", simple, nil},
|
||||
{"multi-title", "@begin " + whens + " - A Title\nwith break @end", "A Title\nwith break", when, "", simple, nil},
|
||||
{"no-title", "@begin " + whens + " - @end", "", when, "", simple, ErrorMissingTitle},
|
||||
{"parse-error", "this is no good", "", when, "", simple, ErrorParsing},
|
||||
{"no-date", "@begin - A Title @end", "A Title", when, "", simple, ErrorMissingDate},
|
||||
{"bad-date", "@begin not-a-real date - A Title @end", "A Title", when, "", simple, ErrorParsing},
|
||||
{"one-field", "@begin " + whens + " - A Title\n@age 41 @end", "A Title", when, "", []Meta{{"age", 41}}, nil},
|
||||
{
|
||||
"two-fields",
|
||||
"@begin " + whens + " - A Title\n@age 41\n@cool true @end",
|
||||
"A Title",
|
||||
when,
|
||||
when, "",
|
||||
[]Meta{{"age", 41}, {"cool", true}},
|
||||
nil,
|
||||
},
|
||||
|
|
@ -177,7 +178,7 @@ func TestEntryUnmarshal(t *testing.T) {
|
|||
"obj-field",
|
||||
"@begin " + whens + " - A Title\n" + `@me {"name":"Dan","coder":true} @end`,
|
||||
"A Title",
|
||||
when,
|
||||
when, "",
|
||||
[]Meta{{"me", json.RawMessage(`{"name":"Dan","coder":true}`)}},
|
||||
nil,
|
||||
},
|
||||
|
|
@ -185,7 +186,7 @@ func TestEntryUnmarshal(t *testing.T) {
|
|||
"nested-field",
|
||||
"@begin " + whens + " - A Title\n@me:name Dan\n@me:coder true @end",
|
||||
"A Title",
|
||||
when,
|
||||
when, "",
|
||||
[]Meta{{"me:name", "Dan"}, {"me:coder", true}},
|
||||
nil,
|
||||
},
|
||||
|
|
@ -193,7 +194,7 @@ func TestEntryUnmarshal(t *testing.T) {
|
|||
"nested-field-dot",
|
||||
"@begin " + whens + " - A Title\n@me:name Dan Jones\n@me:name:nick Danny\n@me:coder true @end",
|
||||
"A Title",
|
||||
when,
|
||||
when, "",
|
||||
[]Meta{{"me:name", "Dan Jones"}, {"me:name:nick", "Danny"}, {"me:coder", true}},
|
||||
nil,
|
||||
},
|
||||
|
|
@ -201,18 +202,18 @@ func TestEntryUnmarshal(t *testing.T) {
|
|||
"json-field",
|
||||
"@begin " + whens + " - Some Guy\n" + `@json {"name":"Dan","coder":true} @end`,
|
||||
"Some Guy",
|
||||
when,
|
||||
when, "",
|
||||
[]Meta{{"name", "Dan"}, {"coder", true}},
|
||||
nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, getEntryUnmarshalTestRunner(tt.in, tt.title, tt.date, tt.fields, tt.err))
|
||||
t.Run(tt.name, getEntryUnmarshalTestRunner(tt.in, tt.title, tt.date, tt.id, tt.fields, tt.err))
|
||||
}
|
||||
}
|
||||
|
||||
func getEntryUnmarshalTestRunner(in string, title string, date time.Time, fields []Meta, err error) func(*testing.T) {
|
||||
func getEntryUnmarshalTestRunner(in string, title string, date time.Time, id string, fields []Meta, err error) func(*testing.T) {
|
||||
return func(t *testing.T) {
|
||||
e := &Entry{}
|
||||
er := e.UnmarshalText([]byte(in))
|
||||
|
|
@ -223,6 +224,9 @@ func getEntryUnmarshalTestRunner(in string, title string, date time.Time, fields
|
|||
|
||||
be.Equal(t, e.Title, title)
|
||||
be.True(t, e.Date.After(date.Add(-time.Second)) && e.Date.Before(date.Add(time.Second)))
|
||||
if id != "" {
|
||||
be.Equal(t, e.ID, id)
|
||||
}
|
||||
for _, f := range fields {
|
||||
got := false
|
||||
for _, m := range e.Fields {
|
||||
|
|
@ -263,46 +267,282 @@ func TestEntryJsonMarshal(t *testing.T) {
|
|||
whens := when.Format(time.RFC3339)
|
||||
simple := []Meta{}
|
||||
tests := []struct {
|
||||
name string
|
||||
title string
|
||||
date time.Time
|
||||
fields []Meta
|
||||
out string
|
||||
err error
|
||||
name string
|
||||
title string
|
||||
date time.Time
|
||||
fields []Meta
|
||||
check func(*testing.T, []byte)
|
||||
wantErr error
|
||||
}{
|
||||
{"simple", "A Title", when, simple, `{"title":"A Title","date":"` + whens + `"}`, nil},
|
||||
{"one-field", "A Title 2", when, []Meta{{"age", 41}}, `{"title":"A Title 2","date":"` + whens + `","age":41}`, nil},
|
||||
{"skip-title-field", "A Title", when, []Meta{{"title", "Different title"}}, `{"title":"A Title","date":"` + whens + `"}`, nil},
|
||||
{"skip-date-field", "A Title", when, []Meta{{"date", when.Add(time.Hour)}}, `{"title":"A Title","date":"` + whens + `"}`, nil},
|
||||
{"skip-dupe-field", "A Title", when, []Meta{{"foo", "bar"}, {"foo", "baz"}}, `{"title":"A Title","date":"` + whens + `","foo": "bar"}`, nil},
|
||||
{"two-fields", "A Title", when, []Meta{{"foo", "bar"}, {"baz", 42}}, `{"title":"A Title","date":"` + whens + `","foo": "bar","baz":42}`, nil},
|
||||
{"empty-title", "", when, simple, "", ErrorMissingTitle},
|
||||
{"empty-date", "A Title", time.Time{}, simple, "", ErrorMissingDate},
|
||||
{"obj-field", "A Title", when, []Meta{{"obj", json.RawMessage(`{"foo":"bar","title":"Sub-title"}`)}}, `{"title":"A Title","date":"` + whens + `","obj":{"foo":"bar","title":"Sub-title"}}`, nil},
|
||||
{"date-field", "A Title", when, []Meta{{"when", when.Add(time.Hour)}}, `{"title":"A Title","date":"` + whens + `","when":"` + when.Add(time.Hour).Format(time.RFC3339) + `"}`, nil},
|
||||
{"json-field", "A Title", when, []Meta{{"json", json.RawMessage(`{"age": 41, "cool": true, "name": "Jim"}`)}}, `{"title":"A Title","date":"` + whens + `","age":41,"cool": true, "name": "Jim"}`, nil},
|
||||
{"nested-field", "A Title", when, []Meta{{"obj:foo", "bar"}, {"obj:title", "Sub-title"}}, `{"title":"A Title","date":"` + whens + `","obj":{"foo":"bar","title":"Sub-title"}}`, nil},
|
||||
{"double-nested-field", "A Title", when, []Meta{{"obj:foo", "bar"}, {"obj:me:name", "Dan"}, {"obj:me:age", 27}}, `{"title":"A Title","date":"` + whens + `","obj":{"foo":"bar","me":{"name":"Dan","age":27}}}`, nil},
|
||||
{"nested-plus-json", "A Title", when, []Meta{{"obj:foo", "bar"}, {"obj:me", json.RawMessage(`{"name":"Dan","age":27}`)}}, `{"title":"A Title","date":"` + whens + `","obj":{"foo":"bar","me":{"name":"Dan","age":27}}}`, nil},
|
||||
{"nested-part", "A Title", when, []Meta{{"obj:foo", "bar"}, {"obj:me", "Dan"}, {"obj:me:age", 27}}, `{"title":"A Title","date":"` + whens + `","obj":{"foo":"bar","me":{".":"Dan","age":27}}}`, nil},
|
||||
{"nested-part-order", "A Title", when, []Meta{{"obj:foo", "bar"}, {"obj:me:age", 27}, {"obj:me", "Dan"}}, `{"title":"A Title","date":"` + whens + `","obj":{"foo":"bar","me":{".":"Dan","age":27}}}`, nil},
|
||||
{"nested-part-order-two", "A Title", when, []Meta{{"obj:foo", "bar"}, {"obj:me:age", 27}, {"obj:me", "Dan"}, {"obj:me:cool", true}}, `{"title":"A Title","date":"` + whens + `","obj":{"foo":"bar","me":{".":"Dan","age":27,"cool":true}}}`, nil},
|
||||
{
|
||||
"simple",
|
||||
"A Title",
|
||||
when,
|
||||
simple,
|
||||
func(t *testing.T, o []byte) {
|
||||
var m map[string]any
|
||||
err := json.Unmarshal(o, &m)
|
||||
be.Err(t, err, nil)
|
||||
be.Equal(t, m["title"].(string), "A Title")
|
||||
be.Equal(t, m["date"].(string), whens)
|
||||
_, hasID := m["id"].(string)
|
||||
be.True(t, hasID)
|
||||
},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"one-field",
|
||||
"A Title 2",
|
||||
when,
|
||||
[]Meta{{"age", 41}},
|
||||
func(t *testing.T, o []byte) {
|
||||
var m map[string]any
|
||||
err := json.Unmarshal(o, &m)
|
||||
be.Err(t, err, nil)
|
||||
be.Equal(t, m["title"].(string), "A Title 2")
|
||||
be.Equal(t, m["date"].(string), whens)
|
||||
be.Equal(t, m["age"].(float64), float64(41))
|
||||
},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"skip-title-field",
|
||||
"A Title",
|
||||
when,
|
||||
[]Meta{{"title", "Different title"}},
|
||||
func(t *testing.T, o []byte) {
|
||||
var m map[string]any
|
||||
err := json.Unmarshal(o, &m)
|
||||
be.Err(t, err, nil)
|
||||
be.Equal(t, m["title"].(string), "A Title")
|
||||
},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"skip-date-field",
|
||||
"A Title",
|
||||
when,
|
||||
[]Meta{{"date", when.Add(time.Hour)}},
|
||||
func(t *testing.T, o []byte) {
|
||||
var m map[string]any
|
||||
err := json.Unmarshal(o, &m)
|
||||
be.Err(t, err, nil)
|
||||
be.Equal(t, m["date"].(string), whens)
|
||||
},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"skip-dupe-field",
|
||||
"A Title",
|
||||
when,
|
||||
[]Meta{{"foo", "bar"}, {"foo", "baz"}},
|
||||
func(t *testing.T, o []byte) {
|
||||
var m map[string]any
|
||||
err := json.Unmarshal(o, &m)
|
||||
be.Err(t, err, nil)
|
||||
be.Equal(t, m["foo"].(string), "bar")
|
||||
},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"two-fields",
|
||||
"A Title",
|
||||
when,
|
||||
[]Meta{{"foo", "bar"}, {"baz", 42}},
|
||||
func(t *testing.T, o []byte) {
|
||||
var m map[string]any
|
||||
err := json.Unmarshal(o, &m)
|
||||
be.Err(t, err, nil)
|
||||
be.Equal(t, m["foo"].(string), "bar")
|
||||
be.Equal(t, m["baz"].(float64), float64(42))
|
||||
},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"empty-title",
|
||||
"",
|
||||
when,
|
||||
simple,
|
||||
nil,
|
||||
ErrorMissingTitle,
|
||||
},
|
||||
{
|
||||
"empty-date",
|
||||
"A Title",
|
||||
time.Time{},
|
||||
simple,
|
||||
nil,
|
||||
ErrorMissingDate,
|
||||
},
|
||||
{
|
||||
"obj-field",
|
||||
"A Title",
|
||||
when,
|
||||
[]Meta{{"obj", json.RawMessage(`{"foo":"bar","title":"Sub-title"}`)}},
|
||||
func(t *testing.T, o []byte) {
|
||||
var m map[string]any
|
||||
err := json.Unmarshal(o, &m)
|
||||
be.Err(t, err, nil)
|
||||
obj, ok := m["obj"].(map[string]any)
|
||||
be.True(t, ok)
|
||||
be.Equal(t, obj["foo"].(string), "bar")
|
||||
be.Equal(t, obj["title"].(string), "Sub-title")
|
||||
},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"date-field",
|
||||
"A Title",
|
||||
when,
|
||||
[]Meta{{"when", when.Add(time.Hour)}},
|
||||
func(t *testing.T, o []byte) {
|
||||
var m map[string]any
|
||||
err := json.Unmarshal(o, &m)
|
||||
be.Err(t, err, nil)
|
||||
be.Equal(t, m["when"].(string), when.Add(time.Hour).Format(time.RFC3339))
|
||||
},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"json-field",
|
||||
"A Title",
|
||||
when,
|
||||
[]Meta{{"json", json.RawMessage(`{"age": 41, "cool": true, "name": "Jim"}`)}},
|
||||
func(t *testing.T, o []byte) {
|
||||
var m map[string]any
|
||||
err := json.Unmarshal(o, &m)
|
||||
be.Err(t, err, nil)
|
||||
be.Equal(t, m["age"].(float64), float64(41))
|
||||
be.Equal(t, m["cool"].(bool), true)
|
||||
be.Equal(t, m["name"].(string), "Jim")
|
||||
},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"nested-field",
|
||||
"A Title",
|
||||
when,
|
||||
[]Meta{{"obj:foo", "bar"}, {"obj:title", "Sub-title"}},
|
||||
func(t *testing.T, o []byte) {
|
||||
var m map[string]any
|
||||
err := json.Unmarshal(o, &m)
|
||||
be.Err(t, err, nil)
|
||||
obj, ok := m["obj"].(map[string]any)
|
||||
be.True(t, ok)
|
||||
be.Equal(t, obj["foo"].(string), "bar")
|
||||
be.Equal(t, obj["title"].(string), "Sub-title")
|
||||
},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"double-nested-field",
|
||||
"A Title",
|
||||
when,
|
||||
[]Meta{{"obj:foo", "bar"}, {"obj:me:name", "Dan"}, {"obj:me:age", 27}},
|
||||
func(t *testing.T, o []byte) {
|
||||
var m map[string]any
|
||||
err := json.Unmarshal(o, &m)
|
||||
be.Err(t, err, nil)
|
||||
obj, ok := m["obj"].(map[string]any)
|
||||
be.True(t, ok)
|
||||
be.Equal(t, obj["foo"].(string), "bar")
|
||||
me, ok := obj["me"].(map[string]any)
|
||||
be.True(t, ok)
|
||||
be.Equal(t, me["name"].(string), "Dan")
|
||||
be.Equal(t, me["age"].(float64), float64(27))
|
||||
},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"nested-plus-json",
|
||||
"A Title",
|
||||
when,
|
||||
[]Meta{{"obj:foo", "bar"}, {"obj:me", json.RawMessage(`{"name":"Dan","age":27}`)}},
|
||||
func(t *testing.T, o []byte) {
|
||||
var m map[string]any
|
||||
err := json.Unmarshal(o, &m)
|
||||
be.Err(t, err, nil)
|
||||
obj, ok := m["obj"].(map[string]any)
|
||||
be.True(t, ok)
|
||||
be.Equal(t, obj["foo"].(string), "bar")
|
||||
me, ok := obj["me"].(map[string]any)
|
||||
be.True(t, ok)
|
||||
be.Equal(t, me["name"].(string), "Dan")
|
||||
be.Equal(t, me["age"].(float64), float64(27))
|
||||
},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"nested-part",
|
||||
"A Title",
|
||||
when,
|
||||
[]Meta{{"obj:foo", "bar"}, {"obj:me", "Dan"}, {"obj:me:age", 27}},
|
||||
func(t *testing.T, o []byte) {
|
||||
var m map[string]any
|
||||
err := json.Unmarshal(o, &m)
|
||||
be.Err(t, err, nil)
|
||||
obj, ok := m["obj"].(map[string]any)
|
||||
be.True(t, ok)
|
||||
be.Equal(t, obj["foo"].(string), "bar")
|
||||
me, ok := obj["me"].(map[string]any)
|
||||
be.True(t, ok)
|
||||
be.Equal(t, me["."].(string), "Dan")
|
||||
be.Equal(t, me["age"].(float64), float64(27))
|
||||
},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"nested-part-order",
|
||||
"A Title",
|
||||
when,
|
||||
[]Meta{{"obj:foo", "bar"}, {"obj:me:age", 27}, {"obj:me", "Dan"}},
|
||||
func(t *testing.T, o []byte) {
|
||||
var m map[string]any
|
||||
err := json.Unmarshal(o, &m)
|
||||
be.Err(t, err, nil)
|
||||
obj, ok := m["obj"].(map[string]any)
|
||||
be.True(t, ok)
|
||||
be.Equal(t, obj["foo"].(string), "bar")
|
||||
me, ok := obj["me"].(map[string]any)
|
||||
be.True(t, ok)
|
||||
be.Equal(t, me["."].(string), "Dan")
|
||||
be.Equal(t, me["age"].(float64), float64(27))
|
||||
},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"nested-part-order-two",
|
||||
"A Title",
|
||||
when,
|
||||
[]Meta{{"obj:foo", "bar"}, {"obj:me:age", 27}, {"obj:me", "Dan"}, {"obj:me:cool", true}},
|
||||
func(t *testing.T, o []byte) {
|
||||
var m map[string]any
|
||||
err := json.Unmarshal(o, &m)
|
||||
be.Err(t, err, nil)
|
||||
obj, ok := m["obj"].(map[string]any)
|
||||
be.True(t, ok)
|
||||
be.Equal(t, obj["foo"].(string), "bar")
|
||||
me, ok := obj["me"].(map[string]any)
|
||||
be.True(t, ok)
|
||||
be.Equal(t, me["."].(string), "Dan")
|
||||
be.Equal(t, me["age"].(float64), float64(27))
|
||||
be.Equal(t, me["cool"].(bool), true)
|
||||
},
|
||||
nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, getEntryJsonMarshalTestRunner(tt.title, tt.date, tt.fields, tt.out, tt.err))
|
||||
}
|
||||
}
|
||||
|
||||
func getEntryJsonMarshalTestRunner(title string, date time.Time, fields []Meta, out string, err error) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
e := Entry{title, date, fields}
|
||||
o, er := json.Marshal(e)
|
||||
if err == nil {
|
||||
bep.JSON(t, o, []byte(out))
|
||||
} else {
|
||||
be.Err(t, er, err)
|
||||
}
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
e := Entry{Title: tt.title, Date: tt.date, Fields: tt.fields}
|
||||
o, er := json.Marshal(e)
|
||||
if tt.wantErr == nil {
|
||||
be.Err(t, er, nil)
|
||||
tt.check(t, o)
|
||||
} else {
|
||||
be.Err(t, er, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue