github.com/olljanat/moby@v1.13.1/pkg/jsonmessage/jsonmessage_test.go (about)

     1  package jsonmessage
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"strings"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/docker/docker/pkg/jsonlog"
    11  	"github.com/docker/docker/pkg/term"
    12  )
    13  
    14  func TestError(t *testing.T) {
    15  	je := JSONError{404, "Not found"}
    16  	if je.Error() != "Not found" {
    17  		t.Fatalf("Expected 'Not found' got '%s'", je.Error())
    18  	}
    19  }
    20  
    21  func TestProgress(t *testing.T) {
    22  	termsz, err := term.GetWinsize(0)
    23  	if err != nil {
    24  		// we can safely ignore the err here
    25  		termsz = nil
    26  	}
    27  	jp := JSONProgress{}
    28  	if jp.String() != "" {
    29  		t.Fatalf("Expected empty string, got '%s'", jp.String())
    30  	}
    31  
    32  	expected := "     1 B"
    33  	jp2 := JSONProgress{Current: 1}
    34  	if jp2.String() != expected {
    35  		t.Fatalf("Expected %q, got %q", expected, jp2.String())
    36  	}
    37  
    38  	expectedStart := "[==========>                                        ]     20 B/100 B"
    39  	if termsz != nil && termsz.Width <= 110 {
    40  		expectedStart = "    20 B/100 B"
    41  	}
    42  	jp3 := JSONProgress{Current: 20, Total: 100, Start: time.Now().Unix()}
    43  	// Just look at the start of the string
    44  	// (the remaining time is really hard to test -_-)
    45  	if jp3.String()[:len(expectedStart)] != expectedStart {
    46  		t.Fatalf("Expected to start with %q, got %q", expectedStart, jp3.String())
    47  	}
    48  
    49  	expected = "[=========================>                         ]     50 B/100 B"
    50  	if termsz != nil && termsz.Width <= 110 {
    51  		expected = "    50 B/100 B"
    52  	}
    53  	jp4 := JSONProgress{Current: 50, Total: 100}
    54  	if jp4.String() != expected {
    55  		t.Fatalf("Expected %q, got %q", expected, jp4.String())
    56  	}
    57  
    58  	// this number can't be negative gh#7136
    59  	expected = "[==================================================>]     50 B"
    60  	if termsz != nil && termsz.Width <= 110 {
    61  		expected = "    50 B"
    62  	}
    63  	jp5 := JSONProgress{Current: 50, Total: 40}
    64  	if jp5.String() != expected {
    65  		t.Fatalf("Expected %q, got %q", expected, jp5.String())
    66  	}
    67  }
    68  
    69  func TestJSONMessageDisplay(t *testing.T) {
    70  	now := time.Now()
    71  	messages := map[JSONMessage][]string{
    72  		// Empty
    73  		JSONMessage{}: {"\n", "\n"},
    74  		// Status
    75  		JSONMessage{
    76  			Status: "status",
    77  		}: {
    78  			"status\n",
    79  			"status\n",
    80  		},
    81  		// General
    82  		JSONMessage{
    83  			Time:   now.Unix(),
    84  			ID:     "ID",
    85  			From:   "From",
    86  			Status: "status",
    87  		}: {
    88  			fmt.Sprintf("%v ID: (from From) status\n", time.Unix(now.Unix(), 0).Format(jsonlog.RFC3339NanoFixed)),
    89  			fmt.Sprintf("%v ID: (from From) status\n", time.Unix(now.Unix(), 0).Format(jsonlog.RFC3339NanoFixed)),
    90  		},
    91  		// General, with nano precision time
    92  		JSONMessage{
    93  			TimeNano: now.UnixNano(),
    94  			ID:       "ID",
    95  			From:     "From",
    96  			Status:   "status",
    97  		}: {
    98  			fmt.Sprintf("%v ID: (from From) status\n", time.Unix(0, now.UnixNano()).Format(jsonlog.RFC3339NanoFixed)),
    99  			fmt.Sprintf("%v ID: (from From) status\n", time.Unix(0, now.UnixNano()).Format(jsonlog.RFC3339NanoFixed)),
   100  		},
   101  		// General, with both times Nano is preferred
   102  		JSONMessage{
   103  			Time:     now.Unix(),
   104  			TimeNano: now.UnixNano(),
   105  			ID:       "ID",
   106  			From:     "From",
   107  			Status:   "status",
   108  		}: {
   109  			fmt.Sprintf("%v ID: (from From) status\n", time.Unix(0, now.UnixNano()).Format(jsonlog.RFC3339NanoFixed)),
   110  			fmt.Sprintf("%v ID: (from From) status\n", time.Unix(0, now.UnixNano()).Format(jsonlog.RFC3339NanoFixed)),
   111  		},
   112  		// Stream over status
   113  		JSONMessage{
   114  			Status: "status",
   115  			Stream: "stream",
   116  		}: {
   117  			"stream",
   118  			"stream",
   119  		},
   120  		// With progress message
   121  		JSONMessage{
   122  			Status:          "status",
   123  			ProgressMessage: "progressMessage",
   124  		}: {
   125  			"status progressMessage",
   126  			"status progressMessage",
   127  		},
   128  		// With progress, stream empty
   129  		JSONMessage{
   130  			Status:   "status",
   131  			Stream:   "",
   132  			Progress: &JSONProgress{Current: 1},
   133  		}: {
   134  			"",
   135  			fmt.Sprintf("%c[2K\rstatus      1 B\r", 27),
   136  		},
   137  	}
   138  
   139  	// The tests :)
   140  	for jsonMessage, expectedMessages := range messages {
   141  		// Without terminal
   142  		data := bytes.NewBuffer([]byte{})
   143  		if err := jsonMessage.Display(data, false); err != nil {
   144  			t.Fatal(err)
   145  		}
   146  		if data.String() != expectedMessages[0] {
   147  			t.Fatalf("Expected [%v], got [%v]", expectedMessages[0], data.String())
   148  		}
   149  		// With terminal
   150  		data = bytes.NewBuffer([]byte{})
   151  		if err := jsonMessage.Display(data, true); err != nil {
   152  			t.Fatal(err)
   153  		}
   154  		if data.String() != expectedMessages[1] {
   155  			t.Fatalf("Expected [%v], got [%v]", expectedMessages[1], data.String())
   156  		}
   157  	}
   158  }
   159  
   160  // Test JSONMessage with an Error. It will return an error with the text as error, not the meaning of the HTTP code.
   161  func TestJSONMessageDisplayWithJSONError(t *testing.T) {
   162  	data := bytes.NewBuffer([]byte{})
   163  	jsonMessage := JSONMessage{Error: &JSONError{404, "Can't find it"}}
   164  
   165  	err := jsonMessage.Display(data, true)
   166  	if err == nil || err.Error() != "Can't find it" {
   167  		t.Fatalf("Expected a JSONError 404, got [%v]", err)
   168  	}
   169  
   170  	jsonMessage = JSONMessage{Error: &JSONError{401, "Anything"}}
   171  	err = jsonMessage.Display(data, true)
   172  	if err == nil || err.Error() != "Authentication is required." {
   173  		t.Fatalf("Expected an error [Authentication is required.], got [%v]", err)
   174  	}
   175  }
   176  
   177  func TestDisplayJSONMessagesStreamInvalidJSON(t *testing.T) {
   178  	var (
   179  		inFd uintptr
   180  	)
   181  	data := bytes.NewBuffer([]byte{})
   182  	reader := strings.NewReader("This is not a 'valid' JSON []")
   183  	inFd, _ = term.GetFdInfo(reader)
   184  
   185  	if err := DisplayJSONMessagesStream(reader, data, inFd, false, nil); err == nil && err.Error()[:17] != "invalid character" {
   186  		t.Fatalf("Should have thrown an error (invalid character in ..), got [%v]", err)
   187  	}
   188  }
   189  
   190  func TestDisplayJSONMessagesStream(t *testing.T) {
   191  	var (
   192  		inFd uintptr
   193  	)
   194  
   195  	messages := map[string][]string{
   196  		// empty string
   197  		"": {
   198  			"",
   199  			""},
   200  		// Without progress & ID
   201  		"{ \"status\": \"status\" }": {
   202  			"status\n",
   203  			"status\n",
   204  		},
   205  		// Without progress, with ID
   206  		"{ \"id\": \"ID\",\"status\": \"status\" }": {
   207  			"ID: status\n",
   208  			fmt.Sprintf("ID: status\n"),
   209  		},
   210  		// With progress
   211  		"{ \"id\": \"ID\", \"status\": \"status\", \"progress\": \"ProgressMessage\" }": {
   212  			"ID: status ProgressMessage",
   213  			fmt.Sprintf("\n%c[%dAID: status ProgressMessage%c[%dB", 27, 1, 27, 1),
   214  		},
   215  		// With progressDetail
   216  		"{ \"id\": \"ID\", \"status\": \"status\", \"progressDetail\": { \"Current\": 1} }": {
   217  			"", // progressbar is disabled in non-terminal
   218  			fmt.Sprintf("\n%c[%dA%c[2K\rID: status      1 B\r%c[%dB", 27, 1, 27, 27, 1),
   219  		},
   220  	}
   221  	for jsonMessage, expectedMessages := range messages {
   222  		data := bytes.NewBuffer([]byte{})
   223  		reader := strings.NewReader(jsonMessage)
   224  		inFd, _ = term.GetFdInfo(reader)
   225  
   226  		// Without terminal
   227  		if err := DisplayJSONMessagesStream(reader, data, inFd, false, nil); err != nil {
   228  			t.Fatal(err)
   229  		}
   230  		if data.String() != expectedMessages[0] {
   231  			t.Fatalf("Expected an [%v], got [%v]", expectedMessages[0], data.String())
   232  		}
   233  
   234  		// With terminal
   235  		data = bytes.NewBuffer([]byte{})
   236  		reader = strings.NewReader(jsonMessage)
   237  		if err := DisplayJSONMessagesStream(reader, data, inFd, true, nil); err != nil {
   238  			t.Fatal(err)
   239  		}
   240  		if data.String() != expectedMessages[1] {
   241  			t.Fatalf("Expected an [%v], got [%v]", expectedMessages[1], data.String())
   242  		}
   243  	}
   244  
   245  }