1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Unexport FastTimeMarshalJSON

Signed-off-by: Daniel Nephin <dnephin@docker.com>
This commit is contained in:
Daniel Nephin 2017-09-22 15:37:16 -04:00
parent 27cfa68af1
commit 7de92de636
7 changed files with 65 additions and 77 deletions

View file

@ -113,18 +113,14 @@ func writeMessageBuf(w io.Writer, m *logger.Message, extra json.RawMessage, buf
}
func marshalMessage(msg *logger.Message, extra json.RawMessage, buf *bytes.Buffer) error {
timestamp, err := jsonlog.FastTimeMarshalJSON(msg.Timestamp)
if err != nil {
return err
}
logLine := msg.Line
if !msg.Partial {
logLine = append(msg.Line, '\n')
}
err = (&jsonlog.JSONLogs{
err := (&jsonlog.JSONLogs{
Log: logLine,
Stream: msg.Source,
Created: timestamp,
Created: msg.Timestamp,
RawAttrs: extra,
}).MarshalJSONBuf(buf)
if err != nil {

View file

@ -105,7 +105,7 @@ func (mj *JSONLog) MarshalJSONBuf(buf *bytes.Buffer) error {
buf.WriteString(`,`)
}
buf.WriteString(`"time":`)
timestamp, err = FastTimeMarshalJSON(mj.Created)
timestamp, err = fastTimeMarshalJSON(mj.Created)
if err != nil {
return err
}

View file

@ -3,6 +3,10 @@ package jsonlog
import (
"regexp"
"testing"
"encoding/json"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestJSONLogMarshalJSON(t *testing.T) {
@ -21,14 +25,8 @@ func TestJSONLogMarshalJSON(t *testing.T) {
}
for jsonLog, expression := range logs {
data, err := jsonLog.MarshalJSON()
if err != nil {
t.Fatal(err)
}
res := string(data)
t.Logf("Result of WriteLog: %q", res)
logRe := regexp.MustCompile(expression)
if !logRe.MatchString(res) {
t.Fatalf("Log line not in expected format [%v]: %q", expression, res)
}
require.NoError(t, err)
assert.Regexp(t, regexp.MustCompile(expression), string(data))
assert.NoError(t, json.Unmarshal(data, &map[string]interface{}{}))
}
}

View file

@ -3,16 +3,15 @@ package jsonlog
import (
"bytes"
"encoding/json"
"time"
"unicode/utf8"
)
// JSONLogs is based on JSONLog.
// It allows marshalling JSONLog from Log as []byte
// and an already marshalled Created timestamp.
// JSONLogs marshals encoded JSONLog objects
type JSONLogs struct {
Log []byte `json:"log,omitempty"`
Stream string `json:"stream,omitempty"`
Created string `json:"time"`
Log []byte `json:"log,omitempty"`
Stream string `json:"stream,omitempty"`
Created time.Time `json:"time"`
// json-encoded bytes
RawAttrs json.RawMessage `json:"attrs,omitempty"`
@ -50,8 +49,14 @@ func (mj *JSONLogs) MarshalJSONBuf(buf *bytes.Buffer) error {
if !first {
buf.WriteString(`,`)
}
created, err := fastTimeMarshalJSON(mj.Created)
if err != nil {
return err
}
buf.WriteString(`"time":`)
buf.WriteString(mj.Created)
buf.WriteString(created)
buf.WriteString(`}`)
return nil
}

View file

@ -2,38 +2,39 @@ package jsonlog
import (
"bytes"
"encoding/json"
"regexp"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestJSONLogsMarshalJSONBuf(t *testing.T) {
logs := map[*JSONLogs]string{
{Log: []byte(`"A log line with \\"`)}: `^{\"log\":\"\\\"A log line with \\\\\\\\\\\"\",\"time\":}$`,
{Log: []byte("A log line")}: `^{\"log\":\"A log line\",\"time\":}$`,
{Log: []byte("A log line with \r")}: `^{\"log\":\"A log line with \\r\",\"time\":}$`,
{Log: []byte("A log line with & < >")}: `^{\"log\":\"A log line with \\u0026 \\u003c \\u003e\",\"time\":}$`,
{Log: []byte("A log line with utf8 : 🚀 ψ ω β")}: `^{\"log\":\"A log line with utf8 : 🚀 ψ ω β\",\"time\":}$`,
{Stream: "stdout"}: `^{\"stream\":\"stdout\",\"time\":}$`,
{Stream: "stdout", Log: []byte("A log line")}: `^{\"log\":\"A log line\",\"stream\":\"stdout\",\"time\":}$`,
{Created: "time"}: `^{\"time\":time}$`,
{}: `^{\"time\":}$`,
{Log: []byte(`"A log line with \\"`)}: `^{\"log\":\"\\\"A log line with \\\\\\\\\\\"\",\"time\":`,
{Log: []byte("A log line")}: `^{\"log\":\"A log line\",\"time\":`,
{Log: []byte("A log line with \r")}: `^{\"log\":\"A log line with \\r\",\"time\":`,
{Log: []byte("A log line with & < >")}: `^{\"log\":\"A log line with \\u0026 \\u003c \\u003e\",\"time\":`,
{Log: []byte("A log line with utf8 : 🚀 ψ ω β")}: `^{\"log\":\"A log line with utf8 : 🚀 ψ ω β\",\"time\":`,
{Stream: "stdout"}: `^{\"stream\":\"stdout\",\"time\":`,
{Stream: "stdout", Log: []byte("A log line")}: `^{\"log\":\"A log line\",\"stream\":\"stdout\",\"time\":`,
{Created: time.Date(2017, 9, 1, 1, 1, 1, 1, time.UTC)}: `^{\"time\":"2017-09-01T01:01:01.000000001Z"}$`,
{}: `^{\"time\":"0001-01-01T00:00:00Z"}$`,
// These ones are a little weird
{Log: []byte("\u2028 \u2029")}: `^{\"log\":\"\\u2028 \\u2029\",\"time\":}$`,
{Log: []byte{0xaF}}: `^{\"log\":\"\\ufffd\",\"time\":}$`,
{Log: []byte{0x7F}}: `^{\"log\":\"\x7f\",\"time\":}$`,
{Log: []byte("\u2028 \u2029")}: `^{\"log\":\"\\u2028 \\u2029\",\"time\":`,
{Log: []byte{0xaF}}: `^{\"log\":\"\\ufffd\",\"time\":`,
{Log: []byte{0x7F}}: `^{\"log\":\"\x7f\",\"time\":`,
// with raw attributes
{Log: []byte("A log line"), RawAttrs: []byte(`{"hello":"world","value":1234}`)}: `^{\"log\":\"A log line\",\"attrs\":{\"hello\":\"world\",\"value\":1234},\"time\":}$`,
{Log: []byte("A log line"), RawAttrs: []byte(`{"hello":"world","value":1234}`)}: `^{\"log\":\"A log line\",\"attrs\":{\"hello\":\"world\",\"value\":1234},\"time\":`,
}
for jsonLog, expression := range logs {
var buf bytes.Buffer
if err := jsonLog.MarshalJSONBuf(&buf); err != nil {
t.Fatal(err)
}
res := buf.String()
t.Logf("Result of WriteLog: %q", res)
logRe := regexp.MustCompile(expression)
if !logRe.MatchString(res) {
t.Fatalf("Log line not in expected format [%v]: %q", expression, res)
}
err := jsonLog.MarshalJSONBuf(&buf)
require.NoError(t, err)
assert.Regexp(t, regexp.MustCompile(expression), buf.String())
assert.NoError(t, json.Unmarshal(buf.Bytes(), &map[string]interface{}{}))
}
}

View file

@ -8,9 +8,9 @@ import (
const jsonFormat = `"` + time.RFC3339Nano + `"`
// FastTimeMarshalJSON avoids one of the extra allocations that
// fastTimeMarshalJSON avoids one of the extra allocations that
// time.MarshalJSON is making.
func FastTimeMarshalJSON(t time.Time) (string, error) {
func fastTimeMarshalJSON(t time.Time) (string, error) {
if y := t.Year(); y < 0 || y >= 10000 {
// RFC 3339 is clear that years are 4 digits exactly.
// See golang.org/issue/4556#c15 for more discussion.

View file

@ -3,45 +3,33 @@ package jsonlog
import (
"testing"
"time"
"github.com/docker/docker/internal/testutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// Testing to ensure 'year' fields is between 0 and 9999
func TestFastTimeMarshalJSONWithInvalidDate(t *testing.T) {
func TestFastTimeMarshalJSONWithInvalidYear(t *testing.T) {
aTime := time.Date(-1, 1, 1, 0, 0, 0, 0, time.Local)
json, err := FastTimeMarshalJSON(aTime)
if err == nil {
t.Fatalf("FastTimeMarshalJSON should throw an error, but was '%v'", json)
}
anotherTime := time.Date(10000, 1, 1, 0, 0, 0, 0, time.Local)
json, err = FastTimeMarshalJSON(anotherTime)
if err == nil {
t.Fatalf("FastTimeMarshalJSON should throw an error, but was '%v'", json)
}
_, err := fastTimeMarshalJSON(aTime)
testutil.ErrorContains(t, err, "year outside of range")
anotherTime := time.Date(10000, 1, 1, 0, 0, 0, 0, time.Local)
_, err = fastTimeMarshalJSON(anotherTime)
testutil.ErrorContains(t, err, "year outside of range")
}
func TestFastTimeMarshalJSON(t *testing.T) {
aTime := time.Date(2015, 5, 29, 11, 1, 2, 3, time.UTC)
json, err := FastTimeMarshalJSON(aTime)
if err != nil {
t.Fatal(err)
}
expected := "\"2015-05-29T11:01:02.000000003Z\""
if json != expected {
t.Fatalf("Expected %v, got %v", expected, json)
}
json, err := fastTimeMarshalJSON(aTime)
require.NoError(t, err)
assert.Equal(t, "\"2015-05-29T11:01:02.000000003Z\"", json)
location, err := time.LoadLocation("Europe/Paris")
if err != nil {
t.Fatal(err)
}
require.NoError(t, err)
aTime = time.Date(2015, 5, 29, 11, 1, 2, 3, location)
json, err = FastTimeMarshalJSON(aTime)
if err != nil {
t.Fatal(err)
}
expected = "\"2015-05-29T11:01:02.000000003+02:00\""
if json != expected {
t.Fatalf("Expected %v, got %v", expected, json)
}
json, err = fastTimeMarshalJSON(aTime)
require.NoError(t, err)
assert.Equal(t, "\"2015-05-29T11:01:02.000000003+02:00\"", json)
}