my-log/models/entry_test.go

189 lines
4.9 KiB
Go

package models
import (
"bufio"
"encoding"
"encoding/json"
"strings"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
// Type assertions
var _ encoding.TextMarshaler = Entry{}
var _ encoding.TextUnmarshaler = new(Entry)
func TestEntryMarshal(t *testing.T) {
when := time.Now()
whens := when.Format(DateFormat)
simple := []Meta{}
nolines := []string{}
tests := []struct {
name string
title string
date time.Time
fields []Meta
first string
lines []string
err error
}{
{"no-title", "", when, simple, "", nolines, ErrorMissingTitle},
{"zero-date", "Empty title", time.Time{}, simple, "", nolines, ErrorMissingDate},
{"one-line", "A Title", when, simple, "@begin " + whens + " - A Title @end", nolines, nil},
{
"one-field",
"Title 2",
when,
[]Meta{{"age", 41}},
"@begin " + whens + " - Title 2",
[]string{"@age 41 @end"},
nil,
},
{
"three-fields",
"Title 3",
when,
[]Meta{{"age", 41}, {"cool", true}, {"name", "Jim"}},
"@begin " + whens + " - Title 3",
[]string{"@age 41", "@cool true", "@name Jim"},
nil,
},
/* uncomment when implemented
{
"json-field",
"Title J",
when,
[]Meta{{"json", json.RawMessage(`{"age": 41, "cool": true, "name": "Jim"}`)}},
"@begin " + whens + " - Title J",
[]string{"@age 41", "@cool true", "@name Jim"},
nil,
},
*/
}
for _, tt := range tests {
t.Run(tt.name, getEntryMarshalTestRunner(tt.title, tt.date, tt.fields, tt.first, tt.lines, tt.err))
}
}
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}
o, er := en.MarshalText()
assert.Equal(t, err, er)
if first == "" {
return
}
if len(lines) == 0 {
assert.Equal(t, first, string(o))
return
}
os := string(o)
assert.Regexp(t, "^"+first, os)
for _, line := range lines {
assert.Regexp(t, "(?m)^"+line, os)
}
}
}
func TestEntryUnmarshal(t *testing.T) {
when := time.Now()
whens := when.Format(DateFormat)
simple := []Meta{}
tests := []struct {
name string
in string
title string
date time.Time
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},
{
"two-fields",
"@begin " + whens + " - A Title\n@age 41\n@cool true @end",
"A Title",
when,
[]Meta{{"age", 41}, {"cool", true}},
nil,
},
{
"obj-field",
"@begin " + whens + " - A Title\n" + `@me {"name":"Dan","coder":true} @end`,
"A Title",
when,
[]Meta{{"me", json.RawMessage(`{"name":"Dan","coder":true}`)}},
nil,
},
/* uncomment when implemented
{
"json-field",
"@begin " + whens + " - Some Guy\n" + `@json {"name":"Dan","coder":true} @end`,
"A Title",
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))
}
}
func getEntryUnmarshalTestRunner(in string, title string, date time.Time, fields []Meta, err error) func(*testing.T) {
return func(t *testing.T) {
e := &Entry{}
er := e.UnmarshalText([]byte(in))
if err != nil {
assert.ErrorIs(t, er, err)
return
}
assert.Equal(t, title, e.Title)
assert.WithinRange(t, e.Date, date.Add(-time.Second), date.Add(time.Second))
for _, f := range fields {
got := false
for _, m := range e.Fields {
var mVal any = m.Value
var fVal any = f.Value
if mJ, ok := m.Value.(json.RawMessage); ok {
mVal = string(mJ)
}
if fJ, ok := f.Value.(json.RawMessage); ok {
fVal = string(fJ)
}
if m.Key == f.Key && mVal == fVal {
got = true
break
}
}
assert.Truef(t, got, "Couldn't find field %+v", f)
}
}
}
func TestScan(t *testing.T) {
in := "@begin date - Title\nlong\n@foo john\njones\n@bar 42@nobody @end"
read := strings.NewReader(in)
scan := bufio.NewScanner(read)
scan.Split(scanEntry)
assert.True(t, scan.Scan())
assert.Equal(t, "@begin date - Title\nlong", scan.Text())
assert.True(t, scan.Scan())
assert.Equal(t, "@foo john\njones", scan.Text())
assert.True(t, scan.Scan())
assert.Equal(t, "@bar 42@nobody", scan.Text())
assert.False(t, scan.Scan())
}