Browse code

Unexport FastTimeMarshalJSON

Signed-off-by: Daniel Nephin <dnephin@docker.com>

Daniel Nephin authored on 2017/09/23 04:37:16
Showing 7 changed files
... ...
@@ -113,18 +113,14 @@ func writeMessageBuf(w io.Writer, m *logger.Message, extra json.RawMessage, buf
113 113
 }
114 114
 
115 115
 func marshalMessage(msg *logger.Message, extra json.RawMessage, buf *bytes.Buffer) error {
116
-	timestamp, err := jsonlog.FastTimeMarshalJSON(msg.Timestamp)
117
-	if err != nil {
118
-		return err
119
-	}
120 116
 	logLine := msg.Line
121 117
 	if !msg.Partial {
122 118
 		logLine = append(msg.Line, '\n')
123 119
 	}
124
-	err = (&jsonlog.JSONLogs{
120
+	err := (&jsonlog.JSONLogs{
125 121
 		Log:      logLine,
126 122
 		Stream:   msg.Source,
127
-		Created:  timestamp,
123
+		Created:  msg.Timestamp,
128 124
 		RawAttrs: extra,
129 125
 	}).MarshalJSONBuf(buf)
130 126
 	if err != nil {
... ...
@@ -105,7 +105,7 @@ func (mj *JSONLog) MarshalJSONBuf(buf *bytes.Buffer) error {
105 105
 		buf.WriteString(`,`)
106 106
 	}
107 107
 	buf.WriteString(`"time":`)
108
-	timestamp, err = FastTimeMarshalJSON(mj.Created)
108
+	timestamp, err = fastTimeMarshalJSON(mj.Created)
109 109
 	if err != nil {
110 110
 		return err
111 111
 	}
... ...
@@ -3,6 +3,10 @@ package jsonlog
3 3
 import (
4 4
 	"regexp"
5 5
 	"testing"
6
+
7
+	"encoding/json"
8
+	"github.com/stretchr/testify/assert"
9
+	"github.com/stretchr/testify/require"
6 10
 )
7 11
 
8 12
 func TestJSONLogMarshalJSON(t *testing.T) {
... ...
@@ -21,14 +25,8 @@ func TestJSONLogMarshalJSON(t *testing.T) {
21 21
 	}
22 22
 	for jsonLog, expression := range logs {
23 23
 		data, err := jsonLog.MarshalJSON()
24
-		if err != nil {
25
-			t.Fatal(err)
26
-		}
27
-		res := string(data)
28
-		t.Logf("Result of WriteLog: %q", res)
29
-		logRe := regexp.MustCompile(expression)
30
-		if !logRe.MatchString(res) {
31
-			t.Fatalf("Log line not in expected format [%v]: %q", expression, res)
32
-		}
24
+		require.NoError(t, err)
25
+		assert.Regexp(t, regexp.MustCompile(expression), string(data))
26
+		assert.NoError(t, json.Unmarshal(data, &map[string]interface{}{}))
33 27
 	}
34 28
 }
... ...
@@ -3,16 +3,15 @@ package jsonlog
3 3
 import (
4 4
 	"bytes"
5 5
 	"encoding/json"
6
+	"time"
6 7
 	"unicode/utf8"
7 8
 )
8 9
 
9
-// JSONLogs is based on JSONLog.
10
-// It allows marshalling JSONLog from Log as []byte
11
-// and an already marshalled Created timestamp.
10
+// JSONLogs marshals encoded JSONLog objects
12 11
 type JSONLogs struct {
13
-	Log     []byte `json:"log,omitempty"`
14
-	Stream  string `json:"stream,omitempty"`
15
-	Created string `json:"time"`
12
+	Log     []byte    `json:"log,omitempty"`
13
+	Stream  string    `json:"stream,omitempty"`
14
+	Created time.Time `json:"time"`
16 15
 
17 16
 	// json-encoded bytes
18 17
 	RawAttrs json.RawMessage `json:"attrs,omitempty"`
... ...
@@ -50,8 +49,14 @@ func (mj *JSONLogs) MarshalJSONBuf(buf *bytes.Buffer) error {
50 50
 	if !first {
51 51
 		buf.WriteString(`,`)
52 52
 	}
53
+
54
+	created, err := fastTimeMarshalJSON(mj.Created)
55
+	if err != nil {
56
+		return err
57
+	}
58
+
53 59
 	buf.WriteString(`"time":`)
54
-	buf.WriteString(mj.Created)
60
+	buf.WriteString(created)
55 61
 	buf.WriteString(`}`)
56 62
 	return nil
57 63
 }
... ...
@@ -2,38 +2,39 @@ package jsonlog
2 2
 
3 3
 import (
4 4
 	"bytes"
5
+	"encoding/json"
5 6
 	"regexp"
6 7
 	"testing"
8
+	"time"
9
+
10
+	"github.com/stretchr/testify/assert"
11
+	"github.com/stretchr/testify/require"
7 12
 )
8 13
 
9 14
 func TestJSONLogsMarshalJSONBuf(t *testing.T) {
10 15
 	logs := map[*JSONLogs]string{
11
-		{Log: []byte(`"A log line with \\"`)}:           `^{\"log\":\"\\\"A log line with \\\\\\\\\\\"\",\"time\":}$`,
12
-		{Log: []byte("A log line")}:                     `^{\"log\":\"A log line\",\"time\":}$`,
13
-		{Log: []byte("A log line with \r")}:             `^{\"log\":\"A log line with \\r\",\"time\":}$`,
14
-		{Log: []byte("A log line with & < >")}:          `^{\"log\":\"A log line with \\u0026 \\u003c \\u003e\",\"time\":}$`,
15
-		{Log: []byte("A log line with utf8 : 🚀 ψ ω β")}: `^{\"log\":\"A log line with utf8 : 🚀 ψ ω β\",\"time\":}$`,
16
-		{Stream: "stdout"}:                              `^{\"stream\":\"stdout\",\"time\":}$`,
17
-		{Stream: "stdout", Log: []byte("A log line")}:   `^{\"log\":\"A log line\",\"stream\":\"stdout\",\"time\":}$`,
18
-		{Created: "time"}:                               `^{\"time\":time}$`,
19
-		{}:                                              `^{\"time\":}$`,
16
+		{Log: []byte(`"A log line with \\"`)}:                  `^{\"log\":\"\\\"A log line with \\\\\\\\\\\"\",\"time\":`,
17
+		{Log: []byte("A log line")}:                            `^{\"log\":\"A log line\",\"time\":`,
18
+		{Log: []byte("A log line with \r")}:                    `^{\"log\":\"A log line with \\r\",\"time\":`,
19
+		{Log: []byte("A log line with & < >")}:                 `^{\"log\":\"A log line with \\u0026 \\u003c \\u003e\",\"time\":`,
20
+		{Log: []byte("A log line with utf8 : 🚀 ψ ω β")}:        `^{\"log\":\"A log line with utf8 : 🚀 ψ ω β\",\"time\":`,
21
+		{Stream: "stdout"}:                                     `^{\"stream\":\"stdout\",\"time\":`,
22
+		{Stream: "stdout", Log: []byte("A log line")}:          `^{\"log\":\"A log line\",\"stream\":\"stdout\",\"time\":`,
23
+		{Created: time.Date(2017, 9, 1, 1, 1, 1, 1, time.UTC)}: `^{\"time\":"2017-09-01T01:01:01.000000001Z"}$`,
24
+
25
+		{}: `^{\"time\":"0001-01-01T00:00:00Z"}$`,
20 26
 		// These ones are a little weird
21
-		{Log: []byte("\u2028 \u2029")}: `^{\"log\":\"\\u2028 \\u2029\",\"time\":}$`,
22
-		{Log: []byte{0xaF}}:            `^{\"log\":\"\\ufffd\",\"time\":}$`,
23
-		{Log: []byte{0x7F}}:            `^{\"log\":\"\x7f\",\"time\":}$`,
27
+		{Log: []byte("\u2028 \u2029")}: `^{\"log\":\"\\u2028 \\u2029\",\"time\":`,
28
+		{Log: []byte{0xaF}}:            `^{\"log\":\"\\ufffd\",\"time\":`,
29
+		{Log: []byte{0x7F}}:            `^{\"log\":\"\x7f\",\"time\":`,
24 30
 		// with raw attributes
25
-		{Log: []byte("A log line"), RawAttrs: []byte(`{"hello":"world","value":1234}`)}: `^{\"log\":\"A log line\",\"attrs\":{\"hello\":\"world\",\"value\":1234},\"time\":}$`,
31
+		{Log: []byte("A log line"), RawAttrs: []byte(`{"hello":"world","value":1234}`)}: `^{\"log\":\"A log line\",\"attrs\":{\"hello\":\"world\",\"value\":1234},\"time\":`,
26 32
 	}
27 33
 	for jsonLog, expression := range logs {
28 34
 		var buf bytes.Buffer
29
-		if err := jsonLog.MarshalJSONBuf(&buf); err != nil {
30
-			t.Fatal(err)
31
-		}
32
-		res := buf.String()
33
-		t.Logf("Result of WriteLog: %q", res)
34
-		logRe := regexp.MustCompile(expression)
35
-		if !logRe.MatchString(res) {
36
-			t.Fatalf("Log line not in expected format [%v]: %q", expression, res)
37
-		}
35
+		err := jsonLog.MarshalJSONBuf(&buf)
36
+		require.NoError(t, err)
37
+		assert.Regexp(t, regexp.MustCompile(expression), buf.String())
38
+		assert.NoError(t, json.Unmarshal(buf.Bytes(), &map[string]interface{}{}))
38 39
 	}
39 40
 }
... ...
@@ -8,9 +8,9 @@ import (
8 8
 
9 9
 const jsonFormat = `"` + time.RFC3339Nano + `"`
10 10
 
11
-// FastTimeMarshalJSON avoids one of the extra allocations that
11
+// fastTimeMarshalJSON avoids one of the extra allocations that
12 12
 // time.MarshalJSON is making.
13
-func FastTimeMarshalJSON(t time.Time) (string, error) {
13
+func fastTimeMarshalJSON(t time.Time) (string, error) {
14 14
 	if y := t.Year(); y < 0 || y >= 10000 {
15 15
 		// RFC 3339 is clear that years are 4 digits exactly.
16 16
 		// See golang.org/issue/4556#c15 for more discussion.
... ...
@@ -3,45 +3,33 @@ package jsonlog
3 3
 import (
4 4
 	"testing"
5 5
 	"time"
6
+
7
+	"github.com/docker/docker/internal/testutil"
8
+	"github.com/stretchr/testify/assert"
9
+	"github.com/stretchr/testify/require"
6 10
 )
7 11
 
8
-// Testing to ensure 'year' fields is between 0 and 9999
9
-func TestFastTimeMarshalJSONWithInvalidDate(t *testing.T) {
12
+func TestFastTimeMarshalJSONWithInvalidYear(t *testing.T) {
10 13
 	aTime := time.Date(-1, 1, 1, 0, 0, 0, 0, time.Local)
11
-	json, err := FastTimeMarshalJSON(aTime)
12
-	if err == nil {
13
-		t.Fatalf("FastTimeMarshalJSON should throw an error, but was '%v'", json)
14
-	}
15
-	anotherTime := time.Date(10000, 1, 1, 0, 0, 0, 0, time.Local)
16
-	json, err = FastTimeMarshalJSON(anotherTime)
17
-	if err == nil {
18
-		t.Fatalf("FastTimeMarshalJSON should throw an error, but was '%v'", json)
19
-	}
14
+	_, err := fastTimeMarshalJSON(aTime)
15
+	testutil.ErrorContains(t, err, "year outside of range")
20 16
 
17
+	anotherTime := time.Date(10000, 1, 1, 0, 0, 0, 0, time.Local)
18
+	_, err = fastTimeMarshalJSON(anotherTime)
19
+	testutil.ErrorContains(t, err, "year outside of range")
21 20
 }
22 21
 
23 22
 func TestFastTimeMarshalJSON(t *testing.T) {
24 23
 	aTime := time.Date(2015, 5, 29, 11, 1, 2, 3, time.UTC)
25
-	json, err := FastTimeMarshalJSON(aTime)
26
-	if err != nil {
27
-		t.Fatal(err)
28
-	}
29
-	expected := "\"2015-05-29T11:01:02.000000003Z\""
30
-	if json != expected {
31
-		t.Fatalf("Expected %v, got %v", expected, json)
32
-	}
24
+	json, err := fastTimeMarshalJSON(aTime)
25
+	require.NoError(t, err)
26
+	assert.Equal(t, "\"2015-05-29T11:01:02.000000003Z\"", json)
33 27
 
34 28
 	location, err := time.LoadLocation("Europe/Paris")
35
-	if err != nil {
36
-		t.Fatal(err)
37
-	}
29
+	require.NoError(t, err)
30
+
38 31
 	aTime = time.Date(2015, 5, 29, 11, 1, 2, 3, location)
39
-	json, err = FastTimeMarshalJSON(aTime)
40
-	if err != nil {
41
-		t.Fatal(err)
42
-	}
43
-	expected = "\"2015-05-29T11:01:02.000000003+02:00\""
44
-	if json != expected {
45
-		t.Fatalf("Expected %v, got %v", expected, json)
46
-	}
32
+	json, err = fastTimeMarshalJSON(aTime)
33
+	require.NoError(t, err)
34
+	assert.Equal(t, "\"2015-05-29T11:01:02.000000003+02:00\"", json)
47 35
 }