Jelajahi Sumber

Add test coverage to pkg/jsonlog

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
Vincent Demeester 10 tahun lalu
induk
melakukan
e7a9a0bed8

+ 12 - 5
pkg/jsonlog/jsonlog_marshalling.go

@@ -52,6 +52,17 @@
 //        buf.WriteString(`}`)
 //        return nil
 // }
+// @@ -81,9 +81,10 @@ func (mj *JSONLog) MarshalJSONBuf(buf *bytes.Buffer) error {
+//         if len(mj.Log) != 0 {
+// -                if first == true {
+// -                       first = false
+// -               } else {
+// -                       buf.WriteString(`,`)
+// -               }
+// +               first = false
+//                 buf.WriteString(`"log":`)
+//                 ffjson_WriteJsonString(buf, mj.Log)
+//         }
 
 package jsonlog
 
@@ -79,11 +90,7 @@ func (mj *JSONLog) MarshalJSONBuf(buf *bytes.Buffer) error {
 	)
 	buf.WriteString(`{`)
 	if len(mj.Log) != 0 {
-		if first == true {
-			first = false
-		} else {
-			buf.WriteString(`,`)
-		}
+		first = false
 		buf.WriteString(`"log":`)
 		ffjson_WriteJsonString(buf, mj.Log)
 	}

+ 34 - 0
pkg/jsonlog/jsonlog_marshalling_test.go

@@ -0,0 +1,34 @@
+package jsonlog
+
+import (
+	"regexp"
+	"testing"
+)
+
+func TestJSONLogMarshalJSON(t *testing.T) {
+	logs := map[JSONLog]string{
+		JSONLog{Log: `"A log line with \\"`}:           `^{\"log\":\"\\\"A log line with \\\\\\\\\\\"\",\"time\":\".{20,}\"}$`,
+		JSONLog{Log: "A log line"}:                     `^{\"log\":\"A log line\",\"time\":\".{20,}\"}$`,
+		JSONLog{Log: "A log line with \r"}:             `^{\"log\":\"A log line with \\r\",\"time\":\".{20,}\"}$`,
+		JSONLog{Log: "A log line with & < >"}:          `^{\"log\":\"A log line with \\u0026 \\u003c \\u003e\",\"time\":\".{20,}\"}$`,
+		JSONLog{Log: "A log line with utf8 : 🚀 ψ ω β"}: `^{\"log\":\"A log line with utf8 : 🚀 ψ ω β\",\"time\":\".{20,}\"}$`,
+		JSONLog{Stream: "stdout"}:                      `^{\"stream\":\"stdout\",\"time\":\".{20,}\"}$`,
+		JSONLog{}:                                      `^{\"time\":\".{20,}\"}$`,
+		// These ones are a little weird
+		JSONLog{Log: "\u2028 \u2029"}:      `^{\"log\":\"\\u2028 \\u2029\",\"time\":\".{20,}\"}$`,
+		JSONLog{Log: string([]byte{0xaF})}: `^{\"log\":\"\\ufffd\",\"time\":\".{20,}\"}$`,
+		JSONLog{Log: string([]byte{0x7F})}: `^{\"log\":\"\x7f\",\"time\":\".{20,}\"}$`,
+	}
+	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)
+		}
+	}
+}

+ 104 - 9
pkg/jsonlog/jsonlog_test.go

@@ -5,6 +5,7 @@ import (
 	"encoding/json"
 	"io/ioutil"
 	"regexp"
+	"strconv"
 	"strings"
 	"testing"
 	"time"
@@ -12,29 +13,123 @@ import (
 	"github.com/docker/docker/pkg/timeutils"
 )
 
-func TestWriteLog(t *testing.T) {
+// Invalid json should return an error
+func TestWriteLogWithInvalidJSON(t *testing.T) {
+	json := strings.NewReader("Invalid json")
+	w := bytes.NewBuffer(nil)
+	if err := WriteLog(json, w, "json", time.Time{}); err == nil {
+		t.Fatalf("Expected an error, got [%v]", w.String())
+	}
+}
+
+// Any format is valid, it will just print it
+func TestWriteLogWithInvalidFormat(t *testing.T) {
+	testLine := "Line that thinks that it is log line from docker\n"
 	var buf bytes.Buffer
 	e := json.NewEncoder(&buf)
+	for i := 0; i < 35; i++ {
+		e.Encode(JSONLog{Log: testLine, Stream: "stdout", Created: time.Now()})
+	}
+	w := bytes.NewBuffer(nil)
+	if err := WriteLog(&buf, w, "invalid format", time.Time{}); err != nil {
+		t.Fatal(err)
+	}
+	res := w.String()
+	t.Logf("Result of WriteLog: %q", res)
+	lines := strings.Split(strings.TrimSpace(res), "\n")
+	expression := "^invalid format Line that thinks that it is log line from docker$"
+	logRe := regexp.MustCompile(expression)
+	expectedLines := 35
+	if len(lines) != expectedLines {
+		t.Fatalf("Must be %v lines but got %d", expectedLines, len(lines))
+	}
+	for _, l := range lines {
+		if !logRe.MatchString(l) {
+			t.Fatalf("Log line not in expected format [%v]: %q", expression, l)
+		}
+	}
+}
+
+// Having multiple Log/Stream element
+func TestWriteLogWithMultipleStreamLog(t *testing.T) {
 	testLine := "Line that thinks that it is log line from docker\n"
-	for i := 0; i < 30; i++ {
+	var buf bytes.Buffer
+	e := json.NewEncoder(&buf)
+	for i := 0; i < 35; i++ {
 		e.Encode(JSONLog{Log: testLine, Stream: "stdout", Created: time.Now()})
 	}
 	w := bytes.NewBuffer(nil)
-	format := timeutils.RFC3339NanoFixed
-	if err := WriteLog(&buf, w, format, time.Time{}); err != nil {
+	if err := WriteLog(&buf, w, "invalid format", time.Time{}); err != nil {
 		t.Fatal(err)
 	}
 	res := w.String()
 	t.Logf("Result of WriteLog: %q", res)
 	lines := strings.Split(strings.TrimSpace(res), "\n")
-	if len(lines) != 30 {
-		t.Fatalf("Must be 30 lines but got %d", len(lines))
+	expression := "^invalid format Line that thinks that it is log line from docker$"
+	logRe := regexp.MustCompile(expression)
+	expectedLines := 35
+	if len(lines) != expectedLines {
+		t.Fatalf("Must be %v lines but got %d", expectedLines, len(lines))
 	}
-	// 30+ symbols, five more can come from system timezone
-	logRe := regexp.MustCompile(`.{30,} Line that thinks that it is log line from docker`)
 	for _, l := range lines {
 		if !logRe.MatchString(l) {
-			t.Fatalf("Log line not in expected format: %q", l)
+			t.Fatalf("Log line not in expected format [%v]: %q", expression, l)
+		}
+	}
+}
+
+// Write log with since after created, it won't print anything
+func TestWriteLogWithDate(t *testing.T) {
+	created, _ := time.Parse("YYYY-MM-dd", "2015-01-01")
+	var buf bytes.Buffer
+	testLine := "Line that thinks that it is log line from docker\n"
+	jsonLog := JSONLog{Log: testLine, Stream: "stdout", Created: created}
+	if err := json.NewEncoder(&buf).Encode(jsonLog); err != nil {
+		t.Fatal(err)
+	}
+	w := bytes.NewBuffer(nil)
+	if err := WriteLog(&buf, w, "json", time.Now()); err != nil {
+		t.Fatal(err)
+	}
+	res := w.String()
+	if res != "" {
+		t.Fatalf("Expected empty log, got [%v]", res)
+	}
+}
+
+// Happy path :)
+func TestWriteLog(t *testing.T) {
+	testLine := "Line that thinks that it is log line from docker\n"
+	format := timeutils.RFC3339NanoFixed
+	logs := map[string][]string{
+		"":     {"35", "^Line that thinks that it is log line from docker$"},
+		"json": {"1", `^{\"log\":\"Line that thinks that it is log line from docker\\n\",\"stream\":\"stdout\",\"time\":.{30,}\"}$`},
+		// 30+ symbols, five more can come from system timezone
+		format: {"35", `.{30,} Line that thinks that it is log line from docker`},
+	}
+	for givenFormat, expressionAndLines := range logs {
+		expectedLines, _ := strconv.Atoi(expressionAndLines[0])
+		expression := expressionAndLines[1]
+		var buf bytes.Buffer
+		e := json.NewEncoder(&buf)
+		for i := 0; i < 35; i++ {
+			e.Encode(JSONLog{Log: testLine, Stream: "stdout", Created: time.Now()})
+		}
+		w := bytes.NewBuffer(nil)
+		if err := WriteLog(&buf, w, givenFormat, time.Time{}); err != nil {
+			t.Fatal(err)
+		}
+		res := w.String()
+		t.Logf("Result of WriteLog: %q", res)
+		lines := strings.Split(strings.TrimSpace(res), "\n")
+		if len(lines) != expectedLines {
+			t.Fatalf("Must be %v lines but got %d", expectedLines, len(lines))
+		}
+		logRe := regexp.MustCompile(expression)
+		for _, l := range lines {
+			if !logRe.MatchString(l) {
+				t.Fatalf("Log line not in expected format [%v]: %q", expression, l)
+			}
 		}
 	}
 }

+ 1 - 5
pkg/jsonlog/jsonlogbytes.go

@@ -21,11 +21,7 @@ func (mj *JSONLogBytes) MarshalJSONBuf(buf *bytes.Buffer) error {
 
 	buf.WriteString(`{`)
 	if len(mj.Log) != 0 {
-		if first == true {
-			first = false
-		} else {
-			buf.WriteString(`,`)
-		}
+		first = false
 		buf.WriteString(`"log":`)
 		ffjson_WriteJsonBytesAsString(buf, mj.Log)
 	}

+ 37 - 0
pkg/jsonlog/jsonlogbytes_test.go

@@ -0,0 +1,37 @@
+package jsonlog
+
+import (
+	"bytes"
+	"regexp"
+	"testing"
+)
+
+func TestJSONLogBytesMarshalJSONBuf(t *testing.T) {
+	logs := map[*JSONLogBytes]string{
+		&JSONLogBytes{Log: []byte(`"A log line with \\"`)}:           `^{\"log\":\"\\\"A log line with \\\\\\\\\\\"\",\"time\":}$`,
+		&JSONLogBytes{Log: []byte("A log line")}:                     `^{\"log\":\"A log line\",\"time\":}$`,
+		&JSONLogBytes{Log: []byte("A log line with \r")}:             `^{\"log\":\"A log line with \\r\",\"time\":}$`,
+		&JSONLogBytes{Log: []byte("A log line with & < >")}:          `^{\"log\":\"A log line with \\u0026 \\u003c \\u003e\",\"time\":}$`,
+		&JSONLogBytes{Log: []byte("A log line with utf8 : 🚀 ψ ω β")}: `^{\"log\":\"A log line with utf8 : 🚀 ψ ω β\",\"time\":}$`,
+		&JSONLogBytes{Stream: "stdout"}:                              `^{\"stream\":\"stdout\",\"time\":}$`,
+		&JSONLogBytes{Stream: "stdout", Log: []byte("A log line")}:   `^{\"log\":\"A log line\",\"stream\":\"stdout\",\"time\":}$`,
+		&JSONLogBytes{Created: "time"}:                               `^{\"time\":time}$`,
+		&JSONLogBytes{}:                                              `^{\"time\":}$`,
+		// These ones are a little weird
+		&JSONLogBytes{Log: []byte("\u2028 \u2029")}: `^{\"log\":\"\\u2028 \\u2029\",\"time\":}$`,
+		&JSONLogBytes{Log: []byte{0xaF}}:            `^{\"log\":\"\\ufffd\",\"time\":}$`,
+		&JSONLogBytes{Log: []byte{0x7F}}:            `^{\"log\":\"\x7f\",\"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)
+		}
+	}
+}