From a0556e0b357e6b986f02cf9d4f6701f79e9164a9 Mon Sep 17 00:00:00 2001 From: Noboru Saito Date: Tue, 27 Aug 2024 21:25:44 +0900 Subject: [PATCH] Implemented CONVERT test --- oviewer/action.go | 3 + oviewer/action_test.go | 48 ++++++ oviewer/content.go | 4 +- oviewer/content_test.go | 44 ++++++ oviewer/convert_align.go | 2 +- oviewer/convert_align_test.go | 73 +++++++++ oviewer/convert_es_test.go | 282 ++++++++++++++++++++++++++++++++++ 7 files changed, 453 insertions(+), 3 deletions(-) diff --git a/oviewer/action.go b/oviewer/action.go index cb0a559..0760106 100644 --- a/oviewer/action.go +++ b/oviewer/action.go @@ -431,6 +431,9 @@ func (root *Root) modeConfig(modeName string) (general, error) { func (root *Root) setConverter(ctx context.Context, name string) { m := root.Doc + if m.general.Converter == name { + return + } m.general.Converter = name m.conv = m.converterType(name) root.Doc.ClearCache() diff --git a/oviewer/action_test.go b/oviewer/action_test.go index 5eee915..6fdaa06 100644 --- a/oviewer/action_test.go +++ b/oviewer/action_test.go @@ -1505,3 +1505,51 @@ func TestRoot_tailSection(t *testing.T) { }) } } + +func TestRoot_setConverter(t *testing.T) { + tcellNewScreen = fakeScreen + defer func() { + tcellNewScreen = tcell.NewScreen + }() + type args struct { + name string + } + tests := []struct { + name string + args args + want Converter + }{ + { + name: "testSetConverterEscape", + args: args{ + name: "es", + }, + want: newESConverter(), + }, + { + name: "testSetConverterRaw", + args: args{ + name: "raw", + }, + want: newRawConverter(), + }, + { + name: "testSetConverterAlign", + args: args{ + name: "align", + }, + want: newAlignConverter(false), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + root := rootHelper(t) + ctx := context.Background() + root.setConverter(ctx, tt.args.name) + got := root.Doc.conv + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("setConverter() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/oviewer/content.go b/oviewer/content.go index 0120ea4..040367b 100644 --- a/oviewer/content.go +++ b/oviewer/content.go @@ -76,8 +76,8 @@ func StrToContents(str string, tabWidth int) contents { // RawStrToContents converts a single-line string into a one line of contents. // Does not interpret escape sequences. // 1 Content matches the characters displayed on the screen. -func RawStrToContents(str string, tabWdith int) contents { - return parseString(newRawConverter(), str, tabWdith) +func RawStrToContents(str string, tabWidth int) contents { + return parseString(newRawConverter(), str, tabWidth) } // parseString converts a string to lineContents. diff --git a/oviewer/content_test.go b/oviewer/content_test.go index 12a210a..71a1fc0 100644 --- a/oviewer/content_test.go +++ b/oviewer/content_test.go @@ -810,3 +810,47 @@ func Test_widthPos_n(t *testing.T) { }) } } + +func TestRawStrToContents(t *testing.T) { + type args struct { + str string + tabWidth int + } + tests := []struct { + name string + args args + want contents + }{ + { + name: "red", + args: args{ + str: "\x1B[31mred\x1B[m", tabWidth: 8, + }, + want: contents{ + {width: 0, style: tcell.StyleDefault, mainc: rune('^'), combc: nil}, + {width: 0, style: tcell.StyleDefault, mainc: rune('['), combc: nil}, + {width: 1, style: tcell.StyleDefault, mainc: rune('['), combc: nil}, + {width: 1, style: tcell.StyleDefault, mainc: rune('3'), combc: nil}, + {width: 1, style: tcell.StyleDefault, mainc: rune('1'), combc: nil}, + {width: 1, style: tcell.StyleDefault, mainc: rune('m'), combc: nil}, + {width: 1, style: tcell.StyleDefault, mainc: rune('r'), combc: nil}, + {width: 1, style: tcell.StyleDefault, mainc: rune('e'), combc: nil}, + {width: 1, style: tcell.StyleDefault, mainc: rune('d'), combc: nil}, + {width: 0, style: tcell.StyleDefault, mainc: rune('^'), combc: nil}, + {width: 0, style: tcell.StyleDefault, mainc: rune('['), combc: nil}, + {width: 1, style: tcell.StyleDefault, mainc: rune('['), combc: nil}, + {width: 1, style: tcell.StyleDefault, mainc: rune('m'), combc: nil}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := RawStrToContents(tt.args.str, tt.args.tabWidth); !reflect.DeepEqual(got, tt.want) { + str, _ := ContentsToStr(got) + str2, _ := ContentsToStr(tt.want) + t.Logf("got: %#v %#v", str, str2) + t.Errorf("RawStrToContents() = \n%v, want \n%v", got, tt.want) + } + }) + } +} diff --git a/oviewer/convert_align.go b/oviewer/convert_align.go index 86822ba..8e90267 100644 --- a/oviewer/convert_align.go +++ b/oviewer/convert_align.go @@ -30,7 +30,7 @@ func newAlignConverter(widthF bool) *align { // Returns true if it is an escape sequence and a non-printing character. func (a *align) convert(st *parseState) bool { if len(st.lc) == 0 { - if a.delimiter == "\t" { + if !a.WidthF && a.delimiter == "\t" { st.tabWidth = 1 } a.reset() diff --git a/oviewer/convert_align_test.go b/oviewer/convert_align_test.go index f0bc78b..4dbb086 100644 --- a/oviewer/convert_align_test.go +++ b/oviewer/convert_align_test.go @@ -43,6 +43,79 @@ func Test_align_convert(t *testing.T) { want: false, wantStr: "a ,b ,c\n", }, + { + name: "convertAlignDelmTab", + fields: fields{ + es: newESConverter(), + maxWidths: []int{1, 2}, + WidthF: false, + delimiter: "\t", + count: 0, + }, + args: args{ + st: &parseState{ + lc: StrToContents("", 8), + mainc: '\n', + }, + }, + want: false, + wantStr: "", + }, + { + name: "convertAlignDelmES", + fields: fields{ + es: newESConverter(), + maxWidths: []int{1, 2}, + WidthF: false, + delimiter: "\t", + count: 0, + }, + args: args{ + st: &parseState{ + lc: StrToContents("", 8), + mainc: '\x1b', + }, + }, + want: true, + wantStr: "", + }, + { + name: "convertAlignNoDelm", + fields: fields{ + es: newESConverter(), + maxWidths: []int{}, + WidthF: false, + delimiter: "\t", + count: 0, + }, + args: args{ + st: &parseState{ + lc: StrToContents("", 8), + mainc: 'a', + }, + }, + want: false, + wantStr: "", + }, + { + name: "convertAlignDelm2", + fields: fields{ + es: newESConverter(), + maxWidths: []int{1, 2}, + WidthF: false, + delimiter: ",", + count: 0, + }, + args: args{ + st: &parseState{ + lc: StrToContents("a,b,", 8), + mainc: 'あ', + }, + }, + want: false, + wantStr: "a,b,", + }, + { name: "convertAlignWidth", fields: fields{ diff --git a/oviewer/convert_es_test.go b/oviewer/convert_es_test.go index 12d304e..ce03a37 100644 --- a/oviewer/convert_es_test.go +++ b/oviewer/convert_es_test.go @@ -7,6 +7,165 @@ import ( "github.com/gdamore/tcell/v2" ) +func Test_escapeSequence_convert(t *testing.T) { + type fields struct { + state int + } + type args struct { + st *parseState + } + tests := []struct { + name string + fields fields + args args + want bool + wantState int + }{ + { + name: "test-escapeSequence", + fields: fields{ + state: ansiText, + }, + args: args{ + st: &parseState{ + mainc: 0x1b, + }, + }, + want: true, + wantState: ansiEscape, + }, + { + name: "test-SubString", + fields: fields{ + state: ansiEscape, + }, + args: args{ + st: &parseState{ + mainc: 'P', + }, + }, + want: true, + wantState: ansiSubstring, + }, + { + name: "test-SubString2", + fields: fields{ + state: ansiSubstring, + }, + args: args{ + st: &parseState{ + mainc: 0x1b, + }, + }, + want: true, + wantState: ansiControlSequence, + }, + { + name: "test-OtherSequence", + fields: fields{ + state: ansiEscape, + }, + args: args{ + st: &parseState{ + mainc: '(', + }, + }, + want: true, + wantState: otherSequence, + }, + { + name: "test-Other", + fields: fields{ + state: ansiEscape, + }, + args: args{ + st: &parseState{ + mainc: '@', + }, + }, + want: false, + wantState: ansiText, + }, + { + name: "test-OtherSequence2", + fields: fields{ + state: otherSequence, + }, + args: args{ + st: &parseState{ + mainc: 'a', + }, + }, + want: true, + wantState: ansiEscape, + }, + { + name: "test-ControlSequence", + fields: fields{ + state: ansiControlSequence, + }, + args: args{ + st: &parseState{ + mainc: 'm', + }, + }, + want: true, + wantState: ansiText, + }, + { + name: "test-ControlSequence2", + fields: fields{ + state: ansiControlSequence, + }, + args: args{ + st: &parseState{ + mainc: 'A', + }, + }, + want: true, + wantState: ansiText, + }, + { + name: "test-SysSequence", + fields: fields{ + state: systemSequence, + }, + args: args{ + st: &parseState{ + mainc: 0x07, + }, + }, + want: true, + wantState: ansiText, + }, + { + name: "test-OscHyperLink", + fields: fields{ + state: oscHyperLink, + }, + args: args{ + st: &parseState{ + mainc: 'a', + }, + }, + want: false, + wantState: ansiText, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + es := newESConverter() + es.state = tt.fields.state + if got := es.convert(tt.args.st); got != tt.want { + t.Errorf("escapeSequence.convert() = %v, want %v", got, tt.want) + } + if es.state != tt.wantState { + t.Errorf("escapeSequence.convert() = %v, want %v", es.state, tt.wantState) + } + }) + } +} + func Test_csToStyle(t *testing.T) { t.Parallel() type args struct { @@ -56,3 +215,126 @@ func Test_csToStyle(t *testing.T) { }) } } + +func Test_parseCSI(t *testing.T) { + type args struct { + params string + } + tests := []struct { + name string + args args + want OVStyle + }{ + { + name: "test-attributes", + args: args{ + params: "2;3;4;5;6;7;8;9", + }, + want: OVStyle{ + Dim: true, + Italic: true, + Underline: true, + Blink: true, + Reverse: true, + StrikeThrough: true, + }, + }, + { + name: "test-attributesErr", + args: args{ + params: "38;38;38", + }, + want: OVStyle{ + Dim: false, + Italic: false, + Underline: false, + Blink: false, + Reverse: false, + StrikeThrough: false, + }, + }, + { + name: "test-atributesNone", + args: args{ + params: "28", + }, + want: OVStyle{ + Dim: false, + Italic: false, + Underline: false, + Blink: false, + Reverse: false, + StrikeThrough: false, + }, + }, + { + name: "test-Default", + args: args{ + params: "49", + }, + want: OVStyle{ + Background: "default", + Dim: false, + Italic: false, + Underline: false, + Blink: false, + Reverse: false, + StrikeThrough: false, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := parseCSI(tt.args.params); !reflect.DeepEqual(got, tt.want) { + t.Errorf("parseCSI() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_colorName(t *testing.T) { + type args struct { + colorNumber int + } + tests := []struct { + name string + args args + want string + }{ + { + name: "test-ColorName1", + args: args{ + colorNumber: 1, + }, + want: "maroon", + }, + { + name: "test-ColorName249", + args: args{ + colorNumber: 249, + }, + want: "#bcbcbc", + }, + { + name: "test-ColorNameNotImplemented", + args: args{ + colorNumber: 999, + }, + want: "", + }, + { + name: "test-ColorNameMinus", + args: args{ + colorNumber: -1, + }, + want: "black", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := colorName(tt.args.colorNumber); got != tt.want { + t.Errorf("colorName() = %v, want %v", got, tt.want) + } + }) + } +}