more testing

master
Jordan Orelli 5 years ago
parent 7910f65eb8
commit 31ed54c71e

@ -45,19 +45,24 @@ func (l *LineWriter) WriteEvent(e *Event) {
} }
buf.WriteRune('[') buf.WriteRune('[')
if e.Path != nil {
buf.WriteString(e.Path.String()) buf.WriteString(e.Path.String())
}
buf.WriteRune(']') buf.WriteRune(']')
buf.WriteRune(' ') buf.WriteRune(' ')
if e.Tags == nil { if e.Tags == nil {
buf.WriteString("[] ") buf.WriteString("[]")
} else { } else {
buf.WriteRune('[') buf.WriteRune('[')
writeTags(buf, e.Tags) writeTags(buf, e.Tags)
buf.WriteString("] ") buf.WriteRune(']')
} }
if e.Text != "" {
buf.WriteRune(' ')
buf.WriteString(strings.ReplaceAll(e.Text, string('\n'), "\n")) buf.WriteString(strings.ReplaceAll(e.Text, string('\n'), "\n"))
}
l.out.Lock() l.out.Lock()
l.out.Write(buf.Bytes()) l.out.Write(buf.Bytes())

@ -7,20 +7,129 @@ import (
) )
func TestLineWriter(t *testing.T) { func TestLineWriter(t *testing.T) {
var buf bytes.Buffer refTime := time.Date(2020, time.January, 13, 12, 26, 47, 999999, time.UTC)
w := NewLineWriter(&buf)
w.WriteEvent(&Event{ tests := []struct {
Level: Debug, name string
Time: time.Now(), event Event
Path: NewPath("alice").Child("bob").Child("carol"), line string
Text: "hey you farthead", }{
{
name: "empty event",
event: Event{},
line: `0001-01-01T00:00:00Z d [] []`,
},
{
name: "just a time",
event: Event{
Time: refTime,
},
line: `2020-01-13T12:26:47Z d [] []`,
},
{
name: "root path only",
event: Event{
Time: refTime,
Path: NewPath("root"),
},
line: `2020-01-13T12:26:47Z d [root] []`,
},
{
name: "child path",
event: Event{
Time: refTime,
Path: NewPath("root").Child("kid"),
},
line: `2020-01-13T12:26:47Z d [root/kid] []`,
},
{
name: "another child path",
event: Event{
Time: refTime,
Path: NewPath("root").Child("kid").Child("fart"),
},
line: `2020-01-13T12:26:47Z d [root/kid/fart] []`,
},
{
name: "a message",
event: Event{
Time: refTime,
Path: NewPath("root").Child("kid").Child("fart"),
Text: "this is a message",
},
line: `2020-01-13T12:26:47Z d [root/kid/fart] [] this is a message`,
},
{
name: "a message with an empty tag",
event: Event{
Time: refTime,
Path: NewPath("root").Child("kid").Child("fart"),
Text: "this is a message",
Tags: &Tags{key: "alert"},
},
line: `2020-01-13T12:26:47Z d [root/kid/fart] [alert] this is a message`,
},
{
name: "a message with two empty tags",
event: Event{
Time: refTime,
Path: NewPath("root").Child("kid").Child("fart"),
Text: "this is a message",
Tags: &Tags{ Tags: &Tags{
key: "poop", key: "zombo-dot-com",
parent: &Tags{key: "alert"},
},
},
line: `2020-01-13T12:26:47Z d [root/kid/fart] [alert+zombo-dot-com] this is a message`,
},
{
name: "a message with an int tag",
event: Event{
Time: refTime,
Path: NewPath("root").Child("kid").Child("fart"),
Text: "this is a message",
Tags: &Tags{
key: "num-users",
value: 15,
},
},
line: `2020-01-13T12:26:47Z d [root/kid/fart] [num-users=15] this is a message`,
},
{
name: "a message with a variety of tags",
event: Event{
Time: refTime,
Path: NewPath("root").Child("kid").Child("fart"),
Text: "this is a message",
Tags: &Tags{
key: "num-users",
value: 15,
parent: &Tags{ parent: &Tags{
key: "num_poops", key: "pi",
value: 27, value: 3.14,
parent: &Tags{
key: "request-id",
value: "b49d31c7-d3bb-4bd3-96fe-34e7c7d2b0a4",
},
},
},
}, },
line: `2020-01-13T12:26:47Z d [root/kid/fart] [request-id=b49d31c7-d3bb-4bd3-96fe-34e7c7d2b0a4+pi=3.14+num-users=15] this is a message`,
}, },
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
var buf bytes.Buffer
w := NewLineWriter(&buf)
w.WriteEvent(&test.event)
line := buf.String()
if line != test.line {
t.Log("expected line does not match observed line")
t.Logf("expected line: '%s'", test.line)
t.Logf("observed line: '%s'", line)
t.Fail()
}
}) })
t.Error(buf.String()) }
} }

@ -1,23 +1,39 @@
package blammo package blammo
// Tags represent event metadata. Tags is an ordered collection of key-value
// pairs where every key is a string. Values are optional, and may be one of
// int, float64, and string. The same key may appear multiple times.
//
// Tags is internally represented by a singly linked list of key-value pairs. A
// Tags struct is immutable once created. The only thing that can be done is to
// create new nodes that point to old nodes. This allows us to continually
// recycle tag nodes that are widely used across an application.
type Tags struct { type Tags struct {
key string key string
value interface{} value interface{}
parent *Tags parent *Tags
} }
// Tag creates a new Tags struct having the given key as its final key, with no
// associated value. All existing keys continue to exist.
func (t *Tags) Tag(key string) *Tags { func (t *Tags) Tag(key string) *Tags {
return &Tags{key: key, parent: t} return &Tags{key: key, parent: t}
} }
// TagInt creates a new Tags struct having the given key-value pair as the
// final key-value pair. All existing key-value pairs continue to exist.
func (t *Tags) TagInt(key string, v int) *Tags { func (t *Tags) TagInt(key string, v int) *Tags {
return &Tags{key: key, value: v, parent: t} return &Tags{key: key, value: v, parent: t}
} }
// TagString creates a new Tags struct having the given key-value pair as the
// final key-value pair. All existing key-value pairs continue to exist.
func (t *Tags) TagString(key, v string) *Tags { func (t *Tags) TagString(key, v string) *Tags {
return &Tags{key: key, value: v, parent: t} return &Tags{key: key, value: v, parent: t}
} }
// TagFloat creates a new Tags struct having the given key-value pair as the
// final key-value pair. All existing key-value pairs continue to exist.
func (t *Tags) TagFloat(key string, v float64) *Tags { func (t *Tags) TagFloat(key string, v float64) *Tags {
return &Tags{key: key, value: v, parent: t} return &Tags{key: key, value: v, parent: t}
} }

Loading…
Cancel
Save