295 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			295 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2014 beego Author. All Rights Reserved.
 | 
						|
//
 | 
						|
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
// you may not use this file except in compliance with the License.
 | 
						|
// You may obtain a copy of the License at
 | 
						|
//
 | 
						|
//      http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
//
 | 
						|
// Unless required by applicable law or agreed to in writing, software
 | 
						|
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
// See the License for the specific language governing permissions and
 | 
						|
// limitations under the License.
 | 
						|
 | 
						|
// +build windows
 | 
						|
 | 
						|
package logs
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"fmt"
 | 
						|
	"syscall"
 | 
						|
	"testing"
 | 
						|
)
 | 
						|
 | 
						|
var GetConsoleScreenBufferInfo = getConsoleScreenBufferInfo
 | 
						|
 | 
						|
func ChangeColor(color uint16) {
 | 
						|
	setConsoleTextAttribute(uintptr(syscall.Stdout), color)
 | 
						|
}
 | 
						|
 | 
						|
func ResetColor() {
 | 
						|
	ChangeColor(uint16(0x0007))
 | 
						|
}
 | 
						|
 | 
						|
func TestWritePlanText(t *testing.T) {
 | 
						|
	inner := bytes.NewBufferString("")
 | 
						|
	w := NewAnsiColorWriter(inner)
 | 
						|
	expected := "plain text"
 | 
						|
	fmt.Fprintf(w, expected)
 | 
						|
	actual := inner.String()
 | 
						|
	if actual != expected {
 | 
						|
		t.Errorf("Get %q, want %q", actual, expected)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestWriteParseText(t *testing.T) {
 | 
						|
	inner := bytes.NewBufferString("")
 | 
						|
	w := NewAnsiColorWriter(inner)
 | 
						|
 | 
						|
	inputTail := "\x1b[0mtail text"
 | 
						|
	expectedTail := "tail text"
 | 
						|
	fmt.Fprintf(w, inputTail)
 | 
						|
	actualTail := inner.String()
 | 
						|
	inner.Reset()
 | 
						|
	if actualTail != expectedTail {
 | 
						|
		t.Errorf("Get %q, want %q", actualTail, expectedTail)
 | 
						|
	}
 | 
						|
 | 
						|
	inputHead := "head text\x1b[0m"
 | 
						|
	expectedHead := "head text"
 | 
						|
	fmt.Fprintf(w, inputHead)
 | 
						|
	actualHead := inner.String()
 | 
						|
	inner.Reset()
 | 
						|
	if actualHead != expectedHead {
 | 
						|
		t.Errorf("Get %q, want %q", actualHead, expectedHead)
 | 
						|
	}
 | 
						|
 | 
						|
	inputBothEnds := "both ends \x1b[0m text"
 | 
						|
	expectedBothEnds := "both ends  text"
 | 
						|
	fmt.Fprintf(w, inputBothEnds)
 | 
						|
	actualBothEnds := inner.String()
 | 
						|
	inner.Reset()
 | 
						|
	if actualBothEnds != expectedBothEnds {
 | 
						|
		t.Errorf("Get %q, want %q", actualBothEnds, expectedBothEnds)
 | 
						|
	}
 | 
						|
 | 
						|
	inputManyEsc := "\x1b\x1b\x1b\x1b[0m many esc"
 | 
						|
	expectedManyEsc := "\x1b\x1b\x1b many esc"
 | 
						|
	fmt.Fprintf(w, inputManyEsc)
 | 
						|
	actualManyEsc := inner.String()
 | 
						|
	inner.Reset()
 | 
						|
	if actualManyEsc != expectedManyEsc {
 | 
						|
		t.Errorf("Get %q, want %q", actualManyEsc, expectedManyEsc)
 | 
						|
	}
 | 
						|
 | 
						|
	expectedSplit := "split  text"
 | 
						|
	for _, ch := range "split \x1b[0m text" {
 | 
						|
		fmt.Fprintf(w, string(ch))
 | 
						|
	}
 | 
						|
	actualSplit := inner.String()
 | 
						|
	inner.Reset()
 | 
						|
	if actualSplit != expectedSplit {
 | 
						|
		t.Errorf("Get %q, want %q", actualSplit, expectedSplit)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
type screenNotFoundError struct {
 | 
						|
	error
 | 
						|
}
 | 
						|
 | 
						|
func writeAnsiColor(expectedText, colorCode string) (actualText string, actualAttributes uint16, err error) {
 | 
						|
	inner := bytes.NewBufferString("")
 | 
						|
	w := NewAnsiColorWriter(inner)
 | 
						|
	fmt.Fprintf(w, "\x1b[%sm%s", colorCode, expectedText)
 | 
						|
 | 
						|
	actualText = inner.String()
 | 
						|
	screenInfo := GetConsoleScreenBufferInfo(uintptr(syscall.Stdout))
 | 
						|
	if screenInfo != nil {
 | 
						|
		actualAttributes = screenInfo.WAttributes
 | 
						|
	} else {
 | 
						|
		err = &screenNotFoundError{}
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
type testParam struct {
 | 
						|
	text       string
 | 
						|
	attributes uint16
 | 
						|
	ansiColor  string
 | 
						|
}
 | 
						|
 | 
						|
func TestWriteAnsiColorText(t *testing.T) {
 | 
						|
	screenInfo := GetConsoleScreenBufferInfo(uintptr(syscall.Stdout))
 | 
						|
	if screenInfo == nil {
 | 
						|
		t.Fatal("Could not get ConsoleScreenBufferInfo")
 | 
						|
	}
 | 
						|
	defer ChangeColor(screenInfo.WAttributes)
 | 
						|
	defaultFgColor := screenInfo.WAttributes & uint16(0x0007)
 | 
						|
	defaultBgColor := screenInfo.WAttributes & uint16(0x0070)
 | 
						|
	defaultFgIntensity := screenInfo.WAttributes & uint16(0x0008)
 | 
						|
	defaultBgIntensity := screenInfo.WAttributes & uint16(0x0080)
 | 
						|
 | 
						|
	fgParam := []testParam{
 | 
						|
		{"foreground black  ", uint16(0x0000 | 0x0000), "30"},
 | 
						|
		{"foreground red    ", uint16(0x0004 | 0x0000), "31"},
 | 
						|
		{"foreground green  ", uint16(0x0002 | 0x0000), "32"},
 | 
						|
		{"foreground yellow ", uint16(0x0006 | 0x0000), "33"},
 | 
						|
		{"foreground blue   ", uint16(0x0001 | 0x0000), "34"},
 | 
						|
		{"foreground magenta", uint16(0x0005 | 0x0000), "35"},
 | 
						|
		{"foreground cyan   ", uint16(0x0003 | 0x0000), "36"},
 | 
						|
		{"foreground white  ", uint16(0x0007 | 0x0000), "37"},
 | 
						|
		{"foreground default", defaultFgColor | 0x0000, "39"},
 | 
						|
		{"foreground light gray   ", uint16(0x0000 | 0x0008 | 0x0000), "90"},
 | 
						|
		{"foreground light red    ", uint16(0x0004 | 0x0008 | 0x0000), "91"},
 | 
						|
		{"foreground light green  ", uint16(0x0002 | 0x0008 | 0x0000), "92"},
 | 
						|
		{"foreground light yellow ", uint16(0x0006 | 0x0008 | 0x0000), "93"},
 | 
						|
		{"foreground light blue   ", uint16(0x0001 | 0x0008 | 0x0000), "94"},
 | 
						|
		{"foreground light magenta", uint16(0x0005 | 0x0008 | 0x0000), "95"},
 | 
						|
		{"foreground light cyan   ", uint16(0x0003 | 0x0008 | 0x0000), "96"},
 | 
						|
		{"foreground light white  ", uint16(0x0007 | 0x0008 | 0x0000), "97"},
 | 
						|
	}
 | 
						|
 | 
						|
	bgParam := []testParam{
 | 
						|
		{"background black  ", uint16(0x0007 | 0x0000), "40"},
 | 
						|
		{"background red    ", uint16(0x0007 | 0x0040), "41"},
 | 
						|
		{"background green  ", uint16(0x0007 | 0x0020), "42"},
 | 
						|
		{"background yellow ", uint16(0x0007 | 0x0060), "43"},
 | 
						|
		{"background blue   ", uint16(0x0007 | 0x0010), "44"},
 | 
						|
		{"background magenta", uint16(0x0007 | 0x0050), "45"},
 | 
						|
		{"background cyan   ", uint16(0x0007 | 0x0030), "46"},
 | 
						|
		{"background white  ", uint16(0x0007 | 0x0070), "47"},
 | 
						|
		{"background default", uint16(0x0007) | defaultBgColor, "49"},
 | 
						|
		{"background light gray   ", uint16(0x0007 | 0x0000 | 0x0080), "100"},
 | 
						|
		{"background light red    ", uint16(0x0007 | 0x0040 | 0x0080), "101"},
 | 
						|
		{"background light green  ", uint16(0x0007 | 0x0020 | 0x0080), "102"},
 | 
						|
		{"background light yellow ", uint16(0x0007 | 0x0060 | 0x0080), "103"},
 | 
						|
		{"background light blue   ", uint16(0x0007 | 0x0010 | 0x0080), "104"},
 | 
						|
		{"background light magenta", uint16(0x0007 | 0x0050 | 0x0080), "105"},
 | 
						|
		{"background light cyan   ", uint16(0x0007 | 0x0030 | 0x0080), "106"},
 | 
						|
		{"background light white  ", uint16(0x0007 | 0x0070 | 0x0080), "107"},
 | 
						|
	}
 | 
						|
 | 
						|
	resetParam := []testParam{
 | 
						|
		{"all reset", defaultFgColor | defaultBgColor | defaultFgIntensity | defaultBgIntensity, "0"},
 | 
						|
		{"all reset", defaultFgColor | defaultBgColor | defaultFgIntensity | defaultBgIntensity, ""},
 | 
						|
	}
 | 
						|
 | 
						|
	boldParam := []testParam{
 | 
						|
		{"bold on", uint16(0x0007 | 0x0008), "1"},
 | 
						|
		{"bold off", uint16(0x0007), "21"},
 | 
						|
	}
 | 
						|
 | 
						|
	underscoreParam := []testParam{
 | 
						|
		{"underscore on", uint16(0x0007 | 0x8000), "4"},
 | 
						|
		{"underscore off", uint16(0x0007), "24"},
 | 
						|
	}
 | 
						|
 | 
						|
	blinkParam := []testParam{
 | 
						|
		{"blink on", uint16(0x0007 | 0x0080), "5"},
 | 
						|
		{"blink off", uint16(0x0007), "25"},
 | 
						|
	}
 | 
						|
 | 
						|
	mixedParam := []testParam{
 | 
						|
		{"both black,   bold, underline, blink", uint16(0x0000 | 0x0000 | 0x0008 | 0x8000 | 0x0080), "30;40;1;4;5"},
 | 
						|
		{"both red,     bold, underline, blink", uint16(0x0004 | 0x0040 | 0x0008 | 0x8000 | 0x0080), "31;41;1;4;5"},
 | 
						|
		{"both green,   bold, underline, blink", uint16(0x0002 | 0x0020 | 0x0008 | 0x8000 | 0x0080), "32;42;1;4;5"},
 | 
						|
		{"both yellow,  bold, underline, blink", uint16(0x0006 | 0x0060 | 0x0008 | 0x8000 | 0x0080), "33;43;1;4;5"},
 | 
						|
		{"both blue,    bold, underline, blink", uint16(0x0001 | 0x0010 | 0x0008 | 0x8000 | 0x0080), "34;44;1;4;5"},
 | 
						|
		{"both magenta, bold, underline, blink", uint16(0x0005 | 0x0050 | 0x0008 | 0x8000 | 0x0080), "35;45;1;4;5"},
 | 
						|
		{"both cyan,    bold, underline, blink", uint16(0x0003 | 0x0030 | 0x0008 | 0x8000 | 0x0080), "36;46;1;4;5"},
 | 
						|
		{"both white,   bold, underline, blink", uint16(0x0007 | 0x0070 | 0x0008 | 0x8000 | 0x0080), "37;47;1;4;5"},
 | 
						|
		{"both default, bold, underline, blink", uint16(defaultFgColor | defaultBgColor | 0x0008 | 0x8000 | 0x0080), "39;49;1;4;5"},
 | 
						|
	}
 | 
						|
 | 
						|
	assertTextAttribute := func(expectedText string, expectedAttributes uint16, ansiColor string) {
 | 
						|
		actualText, actualAttributes, err := writeAnsiColor(expectedText, ansiColor)
 | 
						|
		if actualText != expectedText {
 | 
						|
			t.Errorf("Get %q, want %q", actualText, expectedText)
 | 
						|
		}
 | 
						|
		if err != nil {
 | 
						|
			t.Fatal("Could not get ConsoleScreenBufferInfo")
 | 
						|
		}
 | 
						|
		if actualAttributes != expectedAttributes {
 | 
						|
			t.Errorf("Text: %q, Get 0x%04x, want 0x%04x", expectedText, actualAttributes, expectedAttributes)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	for _, v := range fgParam {
 | 
						|
		ResetColor()
 | 
						|
		assertTextAttribute(v.text, v.attributes, v.ansiColor)
 | 
						|
	}
 | 
						|
 | 
						|
	for _, v := range bgParam {
 | 
						|
		ChangeColor(uint16(0x0070 | 0x0007))
 | 
						|
		assertTextAttribute(v.text, v.attributes, v.ansiColor)
 | 
						|
	}
 | 
						|
 | 
						|
	for _, v := range resetParam {
 | 
						|
		ChangeColor(uint16(0x0000 | 0x0070 | 0x0008))
 | 
						|
		assertTextAttribute(v.text, v.attributes, v.ansiColor)
 | 
						|
	}
 | 
						|
 | 
						|
	ResetColor()
 | 
						|
	for _, v := range boldParam {
 | 
						|
		assertTextAttribute(v.text, v.attributes, v.ansiColor)
 | 
						|
	}
 | 
						|
 | 
						|
	ResetColor()
 | 
						|
	for _, v := range underscoreParam {
 | 
						|
		assertTextAttribute(v.text, v.attributes, v.ansiColor)
 | 
						|
	}
 | 
						|
 | 
						|
	ResetColor()
 | 
						|
	for _, v := range blinkParam {
 | 
						|
		assertTextAttribute(v.text, v.attributes, v.ansiColor)
 | 
						|
	}
 | 
						|
 | 
						|
	for _, v := range mixedParam {
 | 
						|
		ResetColor()
 | 
						|
		assertTextAttribute(v.text, v.attributes, v.ansiColor)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestIgnoreUnknownSequences(t *testing.T) {
 | 
						|
	inner := bytes.NewBufferString("")
 | 
						|
	w := NewModeAnsiColorWriter(inner, OutputNonColorEscSeq)
 | 
						|
 | 
						|
	inputText := "\x1b[=decpath mode"
 | 
						|
	expectedTail := inputText
 | 
						|
	fmt.Fprintf(w, inputText)
 | 
						|
	actualTail := inner.String()
 | 
						|
	inner.Reset()
 | 
						|
	if actualTail != expectedTail {
 | 
						|
		t.Errorf("Get %q, want %q", actualTail, expectedTail)
 | 
						|
	}
 | 
						|
 | 
						|
	inputText = "\x1b[=tailing esc and bracket\x1b["
 | 
						|
	expectedTail = inputText
 | 
						|
	fmt.Fprintf(w, inputText)
 | 
						|
	actualTail = inner.String()
 | 
						|
	inner.Reset()
 | 
						|
	if actualTail != expectedTail {
 | 
						|
		t.Errorf("Get %q, want %q", actualTail, expectedTail)
 | 
						|
	}
 | 
						|
 | 
						|
	inputText = "\x1b[?tailing esc\x1b"
 | 
						|
	expectedTail = inputText
 | 
						|
	fmt.Fprintf(w, inputText)
 | 
						|
	actualTail = inner.String()
 | 
						|
	inner.Reset()
 | 
						|
	if actualTail != expectedTail {
 | 
						|
		t.Errorf("Get %q, want %q", actualTail, expectedTail)
 | 
						|
	}
 | 
						|
 | 
						|
	inputText = "\x1b[1h;3punended color code invalid\x1b3"
 | 
						|
	expectedTail = inputText
 | 
						|
	fmt.Fprintf(w, inputText)
 | 
						|
	actualTail = inner.String()
 | 
						|
	inner.Reset()
 | 
						|
	if actualTail != expectedTail {
 | 
						|
		t.Errorf("Get %q, want %q", actualTail, expectedTail)
 | 
						|
	}
 | 
						|
}
 |