1package streamformatter // import "github.com/docker/docker/pkg/streamformatter"
2
3import (
4	"bytes"
5	"encoding/json"
6	"errors"
7	"strings"
8	"testing"
9
10	"github.com/docker/docker/pkg/jsonmessage"
11	"github.com/google/go-cmp/cmp"
12	"github.com/google/go-cmp/cmp/cmpopts"
13	"gotest.tools/assert"
14	is "gotest.tools/assert/cmp"
15)
16
17func TestRawProgressFormatterFormatStatus(t *testing.T) {
18	sf := rawProgressFormatter{}
19	res := sf.formatStatus("ID", "%s%d", "a", 1)
20	assert.Check(t, is.Equal("a1\r\n", string(res)))
21}
22
23func TestRawProgressFormatterFormatProgress(t *testing.T) {
24	sf := rawProgressFormatter{}
25	jsonProgress := &jsonmessage.JSONProgress{
26		Current: 15,
27		Total:   30,
28		Start:   1,
29	}
30	res := sf.formatProgress("id", "action", jsonProgress, nil)
31	out := string(res)
32	assert.Check(t, strings.HasPrefix(out, "action [===="))
33	assert.Check(t, is.Contains(out, "15B/30B"))
34	assert.Check(t, strings.HasSuffix(out, "\r"))
35}
36
37func TestFormatStatus(t *testing.T) {
38	res := FormatStatus("ID", "%s%d", "a", 1)
39	expected := `{"status":"a1","id":"ID"}` + streamNewline
40	assert.Check(t, is.Equal(expected, string(res)))
41}
42
43func TestFormatError(t *testing.T) {
44	res := FormatError(errors.New("Error for formatter"))
45	expected := `{"errorDetail":{"message":"Error for formatter"},"error":"Error for formatter"}` + "\r\n"
46	assert.Check(t, is.Equal(expected, string(res)))
47}
48
49func TestFormatJSONError(t *testing.T) {
50	err := &jsonmessage.JSONError{Code: 50, Message: "Json error"}
51	res := FormatError(err)
52	expected := `{"errorDetail":{"code":50,"message":"Json error"},"error":"Json error"}` + streamNewline
53	assert.Check(t, is.Equal(expected, string(res)))
54}
55
56func TestJsonProgressFormatterFormatProgress(t *testing.T) {
57	sf := &jsonProgressFormatter{}
58	jsonProgress := &jsonmessage.JSONProgress{
59		Current: 15,
60		Total:   30,
61		Start:   1,
62	}
63	aux := "aux message"
64	res := sf.formatProgress("id", "action", jsonProgress, aux)
65	msg := &jsonmessage.JSONMessage{}
66
67	assert.NilError(t, json.Unmarshal(res, msg))
68
69	rawAux := json.RawMessage(`"` + aux + `"`)
70	expected := &jsonmessage.JSONMessage{
71		ID:       "id",
72		Status:   "action",
73		Aux:      &rawAux,
74		Progress: jsonProgress,
75	}
76	assert.DeepEqual(t, msg, expected, cmpJSONMessageOpt())
77}
78
79func cmpJSONMessageOpt() cmp.Option {
80	progressMessagePath := func(path cmp.Path) bool {
81		return path.String() == "ProgressMessage"
82	}
83	return cmp.Options{
84		cmpopts.IgnoreUnexported(jsonmessage.JSONProgress{}),
85		// Ignore deprecated property that is a derivative of Progress
86		cmp.FilterPath(progressMessagePath, cmp.Ignore()),
87	}
88}
89
90func TestJsonProgressFormatterFormatStatus(t *testing.T) {
91	sf := jsonProgressFormatter{}
92	res := sf.formatStatus("ID", "%s%d", "a", 1)
93	assert.Check(t, is.Equal(`{"status":"a1","id":"ID"}`+streamNewline, string(res)))
94}
95
96func TestNewJSONProgressOutput(t *testing.T) {
97	b := bytes.Buffer{}
98	b.Write(FormatStatus("id", "Downloading"))
99	_ = NewJSONProgressOutput(&b, false)
100	assert.Check(t, is.Equal(`{"status":"Downloading","id":"id"}`+streamNewline, b.String()))
101}
102
103func TestAuxFormatterEmit(t *testing.T) {
104	b := bytes.Buffer{}
105	aux := &AuxFormatter{Writer: &b}
106	sampleAux := &struct {
107		Data string
108	}{"Additional data"}
109	err := aux.Emit("", sampleAux)
110	assert.NilError(t, err)
111	assert.Check(t, is.Equal(`{"aux":{"Data":"Additional data"}}`+streamNewline, b.String()))
112}
113