mirror of https://github.com/mum4k/termdash.git
1712 lines
49 KiB
Go
1712 lines
49 KiB
Go
// Copyright 2019 Google Inc.
|
|
//
|
|
// 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.
|
|
|
|
package sixteen
|
|
|
|
import (
|
|
"image"
|
|
"sort"
|
|
"testing"
|
|
|
|
"github.com/kylelemons/godebug/pretty"
|
|
"github.com/mum4k/termdash/cell"
|
|
"github.com/mum4k/termdash/private/area"
|
|
"github.com/mum4k/termdash/private/canvas"
|
|
"github.com/mum4k/termdash/private/canvas/braille/testbraille"
|
|
"github.com/mum4k/termdash/private/canvas/testcanvas"
|
|
"github.com/mum4k/termdash/private/faketerm"
|
|
"github.com/mum4k/termdash/private/segdisp"
|
|
"github.com/mum4k/termdash/private/segdisp/segment"
|
|
"github.com/mum4k/termdash/private/segdisp/segment/testsegment"
|
|
)
|
|
|
|
func TestDraw(t *testing.T) {
|
|
tests := []struct {
|
|
desc string
|
|
opts []Option
|
|
drawOpts []Option
|
|
cellCanvas image.Rectangle
|
|
// If not nil, it is called before Draw is called and can set, clear or
|
|
// toggle segments or characters.
|
|
update func(*Display) error
|
|
want func(size image.Point) *faketerm.Terminal
|
|
wantErr bool
|
|
wantUpdateErr bool
|
|
}{
|
|
{
|
|
desc: "fails for area not wide enough",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols-1, segdisp.MinRows),
|
|
wantErr: true,
|
|
},
|
|
{
|
|
desc: "fails for area not tall enough",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows-1),
|
|
wantErr: true,
|
|
},
|
|
{
|
|
desc: "fails to set invalid segment (too small)",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
return d.SetSegment(Segment(-1))
|
|
},
|
|
wantUpdateErr: true,
|
|
},
|
|
{
|
|
desc: "fails to set invalid segment (too large)",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
return d.SetSegment(Segment(segmentMax))
|
|
},
|
|
wantUpdateErr: true,
|
|
},
|
|
{
|
|
desc: "fails to clear invalid segment (too small)",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
return d.ClearSegment(Segment(-1))
|
|
},
|
|
wantUpdateErr: true,
|
|
},
|
|
{
|
|
desc: "fails to clear invalid segment (too large)",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
return d.ClearSegment(Segment(segmentMax))
|
|
},
|
|
wantUpdateErr: true,
|
|
},
|
|
{
|
|
desc: "fails to toggle invalid segment (too small)",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
return d.ToggleSegment(Segment(-1))
|
|
},
|
|
wantUpdateErr: true,
|
|
},
|
|
{
|
|
desc: "fails to toggle invalid segment (too large)",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
return d.ToggleSegment(Segment(segmentMax))
|
|
},
|
|
wantUpdateErr: true,
|
|
},
|
|
{
|
|
desc: "empty when no segments set",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
},
|
|
{
|
|
desc: "smallest valid display 6x5, A1",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
return d.SetSegment(A1)
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustHV(bc, image.Rect(1, 0, 4, 1), segment.Horizontal) // A1
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "smallest valid display 6x5, A2",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
return d.SetSegment(A2)
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustHV(bc, image.Rect(5, 0, 8, 1), segment.Horizontal) // A2
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "smallest valid display 6x5, F",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
return d.SetSegment(F)
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustHV(bc, image.Rect(0, 1, 1, 8), segment.Vertical) // F
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "smallest valid display 6x5, J",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
return d.SetSegment(J)
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustHV(bc, image.Rect(4, 1, 5, 8), segment.Vertical) // J
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "smallest valid display 6x5, B",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
return d.SetSegment(B)
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustHV(bc, image.Rect(8, 1, 9, 8), segment.Vertical) // B
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "smallest valid display 6x5, G1",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
return d.SetSegment(G1)
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustHV(bc, image.Rect(1, 8, 4, 9), segment.Horizontal) // G1
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "smallest valid display 6x5, G2",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
return d.SetSegment(G2)
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustHV(bc, image.Rect(5, 8, 8, 9), segment.Horizontal) // G2
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "smallest valid display 6x5, E",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
return d.SetSegment(E)
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustHV(bc, image.Rect(0, 9, 1, 16), segment.Vertical) // E
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "smallest valid display 6x5, M",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
return d.SetSegment(M)
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustHV(bc, image.Rect(4, 9, 5, 16), segment.Vertical) // M
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "smallest valid display 6x5, C",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
return d.SetSegment(C)
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustHV(bc, image.Rect(8, 9, 9, 16), segment.Vertical) // C
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "smallest valid display 6x5, D1",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
return d.SetSegment(D1)
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustHV(bc, image.Rect(1, 16, 4, 17), segment.Horizontal) // D1
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "smallest valid display 6x5, D2",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
return d.SetSegment(D2)
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustHV(bc, image.Rect(5, 16, 8, 17), segment.Horizontal) // D2
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "smallest valid display 6x5, H",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
return d.SetSegment(H)
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustDiagonal(bc, image.Rect(1, 1, 4, 8), 1, segment.LeftToRight) // H
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "smallest valid display 6x5, K",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
return d.SetSegment(K)
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustDiagonal(bc, image.Rect(5, 1, 8, 8), 1, segment.RightToLeft) // K
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
|
|
{
|
|
desc: "smallest valid display 6x5, N",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
return d.SetSegment(N)
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustDiagonal(bc, image.Rect(1, 9, 4, 16), 1, segment.RightToLeft) // N
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "smallest valid display 6x5, L",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
return d.SetSegment(L)
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustDiagonal(bc, image.Rect(5, 9, 8, 16), 1, segment.LeftToRight) // L
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "smallest valid display 6x5, all segments",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
for _, s := range AllSegments() {
|
|
if err := d.SetSegment(s); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustHV(bc, image.Rect(1, 0, 4, 1), segment.Horizontal) // A1
|
|
testsegment.MustHV(bc, image.Rect(5, 0, 8, 1), segment.Horizontal) // A2
|
|
|
|
testsegment.MustHV(bc, image.Rect(0, 1, 1, 8), segment.Vertical) // F
|
|
testsegment.MustHV(bc, image.Rect(4, 1, 5, 8), segment.Vertical) // J
|
|
testsegment.MustHV(bc, image.Rect(8, 1, 9, 8), segment.Vertical) // B
|
|
|
|
testsegment.MustHV(bc, image.Rect(1, 8, 4, 9), segment.Horizontal) // G1
|
|
testsegment.MustHV(bc, image.Rect(5, 8, 8, 9), segment.Horizontal) // G2
|
|
|
|
testsegment.MustHV(bc, image.Rect(0, 9, 1, 16), segment.Vertical) // E
|
|
testsegment.MustHV(bc, image.Rect(4, 9, 5, 16), segment.Vertical) // M
|
|
testsegment.MustHV(bc, image.Rect(8, 9, 9, 16), segment.Vertical) // C
|
|
|
|
testsegment.MustHV(bc, image.Rect(1, 16, 4, 17), segment.Horizontal) // D1
|
|
testsegment.MustHV(bc, image.Rect(5, 16, 8, 17), segment.Horizontal) // D2
|
|
|
|
testsegment.MustDiagonal(bc, image.Rect(1, 1, 4, 8), 1, segment.LeftToRight) // H
|
|
testsegment.MustDiagonal(bc, image.Rect(5, 1, 8, 8), 1, segment.RightToLeft) // K
|
|
testsegment.MustDiagonal(bc, image.Rect(1, 9, 4, 16), 1, segment.RightToLeft) // N
|
|
testsegment.MustDiagonal(bc, image.Rect(5, 9, 8, 16), 1, segment.LeftToRight) // L
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "smallest valid display 6x5, all segments, sets cell options provided to new",
|
|
opts: []Option{
|
|
CellOpts(
|
|
cell.FgColor(cell.ColorRed),
|
|
cell.BgColor(cell.ColorGreen),
|
|
),
|
|
},
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
for _, s := range AllSegments() {
|
|
if err := d.SetSegment(s); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
cOpts := []cell.Option{
|
|
cell.FgColor(cell.ColorRed),
|
|
cell.BgColor(cell.ColorGreen),
|
|
}
|
|
testsegment.MustHV(bc, image.Rect(1, 0, 4, 1), segment.Horizontal, segment.CellOpts(cOpts...)) // A1
|
|
testsegment.MustHV(bc, image.Rect(5, 0, 8, 1), segment.Horizontal, segment.CellOpts(cOpts...)) // A2
|
|
|
|
testsegment.MustHV(bc, image.Rect(0, 1, 1, 8), segment.Vertical, segment.CellOpts(cOpts...)) // F
|
|
testsegment.MustHV(bc, image.Rect(4, 1, 5, 8), segment.Vertical, segment.CellOpts(cOpts...)) // J
|
|
testsegment.MustHV(bc, image.Rect(8, 1, 9, 8), segment.Vertical, segment.CellOpts(cOpts...)) // B
|
|
|
|
testsegment.MustHV(bc, image.Rect(1, 8, 4, 9), segment.Horizontal, segment.CellOpts(cOpts...)) // G1
|
|
testsegment.MustHV(bc, image.Rect(5, 8, 8, 9), segment.Horizontal, segment.CellOpts(cOpts...)) // G2
|
|
|
|
testsegment.MustHV(bc, image.Rect(0, 9, 1, 16), segment.Vertical, segment.CellOpts(cOpts...)) // E
|
|
testsegment.MustHV(bc, image.Rect(4, 9, 5, 16), segment.Vertical, segment.CellOpts(cOpts...)) // M
|
|
testsegment.MustHV(bc, image.Rect(8, 9, 9, 16), segment.Vertical, segment.CellOpts(cOpts...)) // C
|
|
|
|
testsegment.MustHV(bc, image.Rect(1, 16, 4, 17), segment.Horizontal, segment.CellOpts(cOpts...)) // D1
|
|
testsegment.MustHV(bc, image.Rect(5, 16, 8, 17), segment.Horizontal, segment.CellOpts(cOpts...)) // D2
|
|
|
|
testsegment.MustDiagonal(bc, image.Rect(1, 1, 4, 8), 1, segment.LeftToRight, segment.DiagonalCellOpts(cOpts...)) // H
|
|
testsegment.MustDiagonal(bc, image.Rect(5, 1, 8, 8), 1, segment.RightToLeft, segment.DiagonalCellOpts(cOpts...)) // K
|
|
testsegment.MustDiagonal(bc, image.Rect(1, 9, 4, 16), 1, segment.RightToLeft, segment.DiagonalCellOpts(cOpts...)) // N
|
|
testsegment.MustDiagonal(bc, image.Rect(5, 9, 8, 16), 1, segment.LeftToRight, segment.DiagonalCellOpts(cOpts...)) // L
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "smallest valid display 6x5, all segments, sets cell options provided to draw",
|
|
drawOpts: []Option{
|
|
CellOpts(
|
|
cell.FgColor(cell.ColorRed),
|
|
cell.BgColor(cell.ColorGreen),
|
|
),
|
|
},
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
for _, s := range AllSegments() {
|
|
if err := d.SetSegment(s); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
cOpts := []cell.Option{
|
|
cell.FgColor(cell.ColorRed),
|
|
cell.BgColor(cell.ColorGreen),
|
|
}
|
|
testsegment.MustHV(bc, image.Rect(1, 0, 4, 1), segment.Horizontal, segment.CellOpts(cOpts...)) // A1
|
|
testsegment.MustHV(bc, image.Rect(5, 0, 8, 1), segment.Horizontal, segment.CellOpts(cOpts...)) // A2
|
|
|
|
testsegment.MustHV(bc, image.Rect(0, 1, 1, 8), segment.Vertical, segment.CellOpts(cOpts...)) // F
|
|
testsegment.MustHV(bc, image.Rect(4, 1, 5, 8), segment.Vertical, segment.CellOpts(cOpts...)) // J
|
|
testsegment.MustHV(bc, image.Rect(8, 1, 9, 8), segment.Vertical, segment.CellOpts(cOpts...)) // B
|
|
|
|
testsegment.MustHV(bc, image.Rect(1, 8, 4, 9), segment.Horizontal, segment.CellOpts(cOpts...)) // G1
|
|
testsegment.MustHV(bc, image.Rect(5, 8, 8, 9), segment.Horizontal, segment.CellOpts(cOpts...)) // G2
|
|
|
|
testsegment.MustHV(bc, image.Rect(0, 9, 1, 16), segment.Vertical, segment.CellOpts(cOpts...)) // E
|
|
testsegment.MustHV(bc, image.Rect(4, 9, 5, 16), segment.Vertical, segment.CellOpts(cOpts...)) // M
|
|
testsegment.MustHV(bc, image.Rect(8, 9, 9, 16), segment.Vertical, segment.CellOpts(cOpts...)) // C
|
|
|
|
testsegment.MustHV(bc, image.Rect(1, 16, 4, 17), segment.Horizontal, segment.CellOpts(cOpts...)) // D1
|
|
testsegment.MustHV(bc, image.Rect(5, 16, 8, 17), segment.Horizontal, segment.CellOpts(cOpts...)) // D2
|
|
|
|
testsegment.MustDiagonal(bc, image.Rect(1, 1, 4, 8), 1, segment.LeftToRight, segment.DiagonalCellOpts(cOpts...)) // H
|
|
testsegment.MustDiagonal(bc, image.Rect(5, 1, 8, 8), 1, segment.RightToLeft, segment.DiagonalCellOpts(cOpts...)) // K
|
|
testsegment.MustDiagonal(bc, image.Rect(1, 9, 4, 16), 1, segment.RightToLeft, segment.DiagonalCellOpts(cOpts...)) // N
|
|
testsegment.MustDiagonal(bc, image.Rect(5, 9, 8, 16), 1, segment.LeftToRight, segment.DiagonalCellOpts(cOpts...)) // L
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "clears the display",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
for _, s := range AllSegments() {
|
|
if err := d.SetSegment(s); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
d.Clear()
|
|
return nil
|
|
},
|
|
},
|
|
{
|
|
desc: "clears the display and sets cell options",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
d.Clear(CellOpts(cell.FgColor(cell.ColorBlue)))
|
|
return d.SetSegment(A1)
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustHV(bc, image.Rect(1, 0, 4, 1), segment.Horizontal, segment.CellOpts(cell.FgColor(cell.ColorBlue))) // A1
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "clears some segments",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
for _, s := range AllSegments() {
|
|
if err := d.SetSegment(s); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
for _, s := range []Segment{A1, A2, G1, G2, D1, D2, L} {
|
|
if err := d.ClearSegment(s); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustHV(bc, image.Rect(0, 1, 1, 8), segment.Vertical) // F
|
|
testsegment.MustHV(bc, image.Rect(4, 1, 5, 8), segment.Vertical) // J
|
|
testsegment.MustHV(bc, image.Rect(8, 1, 9, 8), segment.Vertical) // B
|
|
|
|
testsegment.MustHV(bc, image.Rect(0, 9, 1, 16), segment.Vertical) // E
|
|
testsegment.MustHV(bc, image.Rect(4, 9, 5, 16), segment.Vertical) // M
|
|
testsegment.MustHV(bc, image.Rect(8, 9, 9, 16), segment.Vertical) // C
|
|
|
|
testsegment.MustDiagonal(bc, image.Rect(1, 1, 4, 8), 1, segment.LeftToRight) // H
|
|
testsegment.MustDiagonal(bc, image.Rect(5, 1, 8, 8), 1, segment.RightToLeft) // K
|
|
testsegment.MustDiagonal(bc, image.Rect(1, 9, 4, 16), 1, segment.RightToLeft) // N
|
|
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "toggles some segments off",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
for _, s := range AllSegments() {
|
|
if err := d.SetSegment(s); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
for _, s := range []Segment{A1, A2, G1, G2, D1, D2, L} {
|
|
if err := d.ToggleSegment(s); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustHV(bc, image.Rect(0, 1, 1, 8), segment.Vertical) // F
|
|
testsegment.MustHV(bc, image.Rect(4, 1, 5, 8), segment.Vertical) // J
|
|
testsegment.MustHV(bc, image.Rect(8, 1, 9, 8), segment.Vertical) // B
|
|
|
|
testsegment.MustHV(bc, image.Rect(0, 9, 1, 16), segment.Vertical) // E
|
|
testsegment.MustHV(bc, image.Rect(4, 9, 5, 16), segment.Vertical) // M
|
|
testsegment.MustHV(bc, image.Rect(8, 9, 9, 16), segment.Vertical) // C
|
|
|
|
testsegment.MustDiagonal(bc, image.Rect(1, 1, 4, 8), 1, segment.LeftToRight) // H
|
|
testsegment.MustDiagonal(bc, image.Rect(5, 1, 8, 8), 1, segment.RightToLeft) // K
|
|
testsegment.MustDiagonal(bc, image.Rect(1, 9, 4, 16), 1, segment.RightToLeft) // N
|
|
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "toggles some segments on",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
for _, s := range []Segment{A1, A2, G1, G2, D1, D2, L} {
|
|
if err := d.ToggleSegment(s); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustHV(bc, image.Rect(1, 0, 4, 1), segment.Horizontal) // A1
|
|
testsegment.MustHV(bc, image.Rect(5, 0, 8, 1), segment.Horizontal) // A2
|
|
|
|
testsegment.MustHV(bc, image.Rect(1, 8, 4, 9), segment.Horizontal) // G1
|
|
testsegment.MustHV(bc, image.Rect(5, 8, 8, 9), segment.Horizontal) // G2
|
|
|
|
testsegment.MustHV(bc, image.Rect(1, 16, 4, 17), segment.Horizontal) // D1
|
|
testsegment.MustHV(bc, image.Rect(5, 16, 8, 17), segment.Horizontal) // D2
|
|
|
|
testsegment.MustDiagonal(bc, image.Rect(5, 9, 8, 16), 1, segment.LeftToRight) // L
|
|
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "set is idempotent",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
if err := d.SetSegment(A1); err != nil {
|
|
return err
|
|
}
|
|
return d.SetSegment(A1)
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustHV(bc, image.Rect(1, 0, 4, 1), segment.Horizontal) // A1
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "clear is idempotent",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows),
|
|
update: func(d *Display) error {
|
|
if err := d.SetSegment(A1); err != nil {
|
|
return err
|
|
}
|
|
if err := d.ClearSegment(A1); err != nil {
|
|
return err
|
|
}
|
|
return d.ClearSegment(A1)
|
|
},
|
|
},
|
|
{
|
|
desc: "segment width of two",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols*2, segdisp.MinRows*2),
|
|
update: func(d *Display) error {
|
|
for _, s := range AllSegments() {
|
|
if err := d.SetSegment(s); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustHV(bc, image.Rect(2, 0, 10, 2), segment.Horizontal) // A1
|
|
testsegment.MustHV(bc, image.Rect(12, 0, 20, 2), segment.Horizontal) // A2
|
|
|
|
testsegment.MustHV(bc, image.Rect(0, 2, 2, 18), segment.Vertical) // F
|
|
testsegment.MustHV(bc, image.Rect(10, 2, 12, 18), segment.Vertical, segment.SkipSlopesLTE(2)) // J
|
|
testsegment.MustHV(bc, image.Rect(20, 2, 22, 18), segment.Vertical, segment.ReverseSlopes()) // B
|
|
|
|
testsegment.MustHV(bc, image.Rect(2, 18, 10, 20), segment.Horizontal, segment.SkipSlopesLTE(2)) // G1
|
|
testsegment.MustHV(bc, image.Rect(12, 18, 20, 20), segment.Horizontal, segment.SkipSlopesLTE(2)) // G2
|
|
|
|
testsegment.MustHV(bc, image.Rect(0, 20, 2, 36), segment.Vertical) // E
|
|
testsegment.MustHV(bc, image.Rect(10, 20, 12, 36), segment.Vertical, segment.SkipSlopesLTE(2)) // M
|
|
testsegment.MustHV(bc, image.Rect(20, 20, 22, 36), segment.Vertical, segment.ReverseSlopes()) // C
|
|
|
|
testsegment.MustHV(bc, image.Rect(2, 36, 10, 38), segment.Horizontal, segment.ReverseSlopes()) // D1
|
|
testsegment.MustHV(bc, image.Rect(12, 36, 20, 38), segment.Horizontal, segment.ReverseSlopes()) // D2
|
|
|
|
testsegment.MustDiagonal(bc, image.Rect(3, 3, 9, 17), 2, segment.LeftToRight) // H
|
|
testsegment.MustDiagonal(bc, image.Rect(13, 3, 19, 17), 2, segment.RightToLeft) // K
|
|
testsegment.MustDiagonal(bc, image.Rect(3, 21, 9, 35), 2, segment.RightToLeft) // N
|
|
testsegment.MustDiagonal(bc, image.Rect(13, 21, 19, 35), 2, segment.LeftToRight) // L
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "segment width of three",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols*3, segdisp.MinRows*3),
|
|
update: func(d *Display) error {
|
|
for _, s := range AllSegments() {
|
|
if err := d.SetSegment(s); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustHV(bc, image.Rect(2, 0, 16, 3), segment.Horizontal) // A1
|
|
testsegment.MustHV(bc, image.Rect(17, 0, 31, 3), segment.Horizontal) // A2
|
|
|
|
testsegment.MustHV(bc, image.Rect(0, 2, 3, 28), segment.Vertical) // F
|
|
testsegment.MustHV(bc, image.Rect(15, 2, 18, 28), segment.Vertical) // J
|
|
testsegment.MustHV(bc, image.Rect(30, 2, 33, 28), segment.Vertical) // B
|
|
|
|
testsegment.MustHV(bc, image.Rect(2, 27, 16, 30), segment.Horizontal) // G1
|
|
testsegment.MustHV(bc, image.Rect(17, 27, 31, 30), segment.Horizontal) // G2
|
|
|
|
testsegment.MustHV(bc, image.Rect(0, 29, 3, 55), segment.Vertical) // E
|
|
testsegment.MustHV(bc, image.Rect(15, 29, 18, 55), segment.Vertical) // M
|
|
testsegment.MustHV(bc, image.Rect(30, 29, 33, 55), segment.Vertical) // C
|
|
|
|
testsegment.MustHV(bc, image.Rect(2, 54, 16, 57), segment.Horizontal) // D1
|
|
testsegment.MustHV(bc, image.Rect(17, 54, 31, 57), segment.Horizontal) // D2
|
|
|
|
testsegment.MustDiagonal(bc, image.Rect(3, 3, 15, 27), 3, segment.LeftToRight) // H
|
|
testsegment.MustDiagonal(bc, image.Rect(18, 3, 30, 27), 3, segment.RightToLeft) // K
|
|
testsegment.MustDiagonal(bc, image.Rect(3, 30, 15, 54), 3, segment.RightToLeft) // N
|
|
testsegment.MustDiagonal(bc, image.Rect(18, 30, 30, 54), 3, segment.LeftToRight) // L
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "segment with even width is changed to odd",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols*4, segdisp.MinRows*4),
|
|
update: func(d *Display) error {
|
|
for _, s := range AllSegments() {
|
|
if err := d.SetSegment(s); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustHV(bc, image.Rect(4, 0, 21, 5), segment.Horizontal) // A1
|
|
testsegment.MustHV(bc, image.Rect(24, 0, 41, 5), segment.Horizontal) // A2
|
|
|
|
testsegment.MustHV(bc, image.Rect(0, 4, 5, 37), segment.Vertical) // F
|
|
testsegment.MustHV(bc, image.Rect(20, 4, 25, 37), segment.Vertical) // J
|
|
testsegment.MustHV(bc, image.Rect(40, 4, 45, 37), segment.Vertical) // B
|
|
|
|
testsegment.MustHV(bc, image.Rect(4, 36, 21, 41), segment.Horizontal) // G1
|
|
testsegment.MustHV(bc, image.Rect(24, 36, 41, 41), segment.Horizontal) // G2
|
|
|
|
testsegment.MustHV(bc, image.Rect(0, 40, 5, 73), segment.Vertical) // E
|
|
testsegment.MustHV(bc, image.Rect(20, 40, 25, 73), segment.Vertical) // M
|
|
testsegment.MustHV(bc, image.Rect(40, 40, 45, 73), segment.Vertical) // C
|
|
|
|
testsegment.MustHV(bc, image.Rect(4, 72, 21, 77), segment.Horizontal) // D1
|
|
testsegment.MustHV(bc, image.Rect(24, 72, 41, 77), segment.Horizontal) // D2
|
|
|
|
testsegment.MustDiagonal(bc, image.Rect(6, 6, 19, 35), 5, segment.LeftToRight) // H
|
|
testsegment.MustDiagonal(bc, image.Rect(26, 6, 39, 35), 5, segment.RightToLeft) // K
|
|
testsegment.MustDiagonal(bc, image.Rect(6, 42, 19, 71), 5, segment.RightToLeft) // N
|
|
testsegment.MustDiagonal(bc, image.Rect(26, 42, 39, 71), 5, segment.LeftToRight) // L
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
{
|
|
desc: "segment with odd width and e√en peak to peak distance is changed to odd",
|
|
cellCanvas: image.Rect(0, 0, segdisp.MinCols*7, segdisp.MinRows*7),
|
|
update: func(d *Display) error {
|
|
for _, s := range AllSegments() {
|
|
if err := d.SetSegment(s); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
},
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
bc := testbraille.MustNew(ft.Area())
|
|
|
|
testsegment.MustHV(bc, image.Rect(7, 0, 39, 9), segment.Horizontal) // A1
|
|
testsegment.MustHV(bc, image.Rect(44, 0, 76, 9), segment.Horizontal) // A2
|
|
|
|
testsegment.MustHV(bc, image.Rect(0, 7, 9, 67), segment.Vertical) // F
|
|
testsegment.MustHV(bc, image.Rect(37, 7, 46, 67), segment.Vertical) // J
|
|
testsegment.MustHV(bc, image.Rect(74, 7, 83, 67), segment.Vertical) // B
|
|
|
|
testsegment.MustHV(bc, image.Rect(7, 65, 39, 74), segment.Horizontal) // G1
|
|
testsegment.MustHV(bc, image.Rect(44, 65, 76, 74), segment.Horizontal) // G2
|
|
|
|
testsegment.MustHV(bc, image.Rect(0, 72, 9, 132), segment.Vertical) // E
|
|
testsegment.MustHV(bc, image.Rect(37, 72, 46, 132), segment.Vertical) // M
|
|
testsegment.MustHV(bc, image.Rect(74, 72, 83, 132), segment.Vertical) // C
|
|
|
|
testsegment.MustHV(bc, image.Rect(7, 130, 39, 139), segment.Horizontal) // D1
|
|
testsegment.MustHV(bc, image.Rect(44, 130, 76, 139), segment.Horizontal) // D2
|
|
|
|
testsegment.MustDiagonal(bc, image.Rect(10, 10, 36, 64), 9, segment.LeftToRight) // H
|
|
testsegment.MustDiagonal(bc, image.Rect(47, 10, 73, 64), 9, segment.RightToLeft) // K
|
|
testsegment.MustDiagonal(bc, image.Rect(10, 75, 36, 129), 9, segment.RightToLeft) // N
|
|
testsegment.MustDiagonal(bc, image.Rect(47, 75, 73, 129), 9, segment.LeftToRight) // L
|
|
testbraille.MustApply(bc, ft)
|
|
return ft
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
d := New(tc.opts...)
|
|
if tc.update != nil {
|
|
err := tc.update(d)
|
|
if (err != nil) != tc.wantUpdateErr {
|
|
t.Errorf("tc.update => unexpected error: %v, wantUpdateErr: %v", err, tc.wantUpdateErr)
|
|
}
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
cvs, err := canvas.New(tc.cellCanvas)
|
|
if err != nil {
|
|
t.Fatalf("canvas.New => unexpected error: %v", err)
|
|
}
|
|
|
|
{
|
|
err := d.Draw(cvs, tc.drawOpts...)
|
|
if (err != nil) != tc.wantErr {
|
|
t.Errorf("Draw => unexpected error: %v, wantErr: %v", err, tc.wantErr)
|
|
}
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
size := area.Size(tc.cellCanvas)
|
|
want := faketerm.MustNew(size)
|
|
if tc.want != nil {
|
|
want = tc.want(size)
|
|
}
|
|
|
|
got, err := faketerm.New(size)
|
|
if err != nil {
|
|
t.Fatalf("faketerm.New => unexpected error: %v", err)
|
|
}
|
|
if err := cvs.Apply(got); err != nil {
|
|
t.Fatalf("bc.Apply => unexpected error: %v", err)
|
|
}
|
|
if diff := faketerm.Diff(want, got); diff != "" {
|
|
t.Fatalf("Draw => %v", diff)
|
|
}
|
|
|
|
})
|
|
}
|
|
}
|
|
|
|
// mustDrawSegments returns a fake terminal of the specified size with the
|
|
// segments drawn on it or panics.
|
|
func mustDrawSegments(size image.Point, seg ...Segment) *faketerm.Terminal {
|
|
ft := faketerm.MustNew(size)
|
|
cvs := testcanvas.MustNew(ft.Area())
|
|
|
|
d := New()
|
|
for _, s := range seg {
|
|
if err := d.SetSegment(s); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
if err := d.Draw(cvs); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
testcanvas.MustApply(cvs, ft)
|
|
return ft
|
|
}
|
|
|
|
func TestSetCharacter(t *testing.T) {
|
|
tests := []struct {
|
|
desc string
|
|
char rune
|
|
// If not nil, it is called before Draw is called and can set, clear or
|
|
// toggle segments or characters.
|
|
update func(*Display) error
|
|
want func(size image.Point) *faketerm.Terminal
|
|
wantErr bool
|
|
}{
|
|
{
|
|
desc: "fails on unsupported character",
|
|
char: '←',
|
|
wantErr: true,
|
|
},
|
|
{
|
|
desc: "displays ' '",
|
|
char: ' ',
|
|
},
|
|
{
|
|
desc: "doesn't clear the display",
|
|
update: func(d *Display) error {
|
|
return d.SetSegment(A2)
|
|
},
|
|
char: 'W',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, F, E, N, L, C, B, A2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '!'",
|
|
char: '!',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, B, C)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '\"'",
|
|
char: '"',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, J, B)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '#'",
|
|
char: '#',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, J, B, G1, G2, M, C, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '$'",
|
|
char: '$',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, F, J, G1, G2, M, C, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '%'",
|
|
char: '%',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, F, J, K, G1, G2, N, M, C, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '&'",
|
|
char: '&',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, H, J, G1, E, L, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '",
|
|
char: '\'',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, J)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '('",
|
|
char: '(',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, K, L)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays ')'",
|
|
char: ')',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, H, N)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '*'",
|
|
char: '*',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, H, J, K, G1, G2, N, M, L)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '+'",
|
|
char: '+',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, J, G1, G2, M)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays ','",
|
|
char: ',',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, N)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '-'",
|
|
char: '-',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, G1, G2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '/'",
|
|
char: '/',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, N, K)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '0'",
|
|
char: '0',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, F, K, B, E, N, C, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '1'",
|
|
char: '1',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, K, B, C)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '2'",
|
|
char: '2',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, B, G1, G2, E, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '3'",
|
|
char: '3',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, B, G2, C, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '4'",
|
|
char: '4',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, F, B, G1, G2, C)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '5'",
|
|
char: '5',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, F, G1, L, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '6'",
|
|
char: '6',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, F, G1, G2, E, C, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '7'",
|
|
char: '7',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, B, C)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '8'",
|
|
char: '8',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, F, B, G1, G2, E, C, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '9'",
|
|
char: '9',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, F, B, G1, G2, C, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays ':'",
|
|
char: ':',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, J, M)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays ';'",
|
|
char: ';',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, J, N)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '<'",
|
|
char: '<',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, K, G1, L)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '='",
|
|
char: '=',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, G1, G2, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '>'",
|
|
char: '>',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, H, G2, N)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '?'",
|
|
char: '?',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, B, G2, M)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '@'",
|
|
char: '@',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, F, J, B, G2, E, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'A'",
|
|
char: 'A',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, F, B, G1, G2, E, C)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'B'",
|
|
char: 'B',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, J, B, G2, M, C, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'C'",
|
|
char: 'C',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, F, E, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'D'",
|
|
char: 'D',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, J, B, M, C, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'E'",
|
|
char: 'E',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, F, G1, E, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'F'",
|
|
char: 'F',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, F, G1, E)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'G'",
|
|
char: 'G',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, F, G2, E, C, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'H'",
|
|
char: 'H',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, F, B, G1, G2, E, C)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'I'",
|
|
char: 'I',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, J, M, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'J'",
|
|
char: 'J',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, B, E, C, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'K'",
|
|
char: 'K',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, F, K, G1, E, L)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'L'",
|
|
char: 'L',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, F, E, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'M'",
|
|
char: 'M',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, F, H, K, B, E, C)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'N'",
|
|
char: 'N',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, F, H, B, E, L, C)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'O'",
|
|
char: 'O',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, F, B, E, C, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'P'",
|
|
char: 'P',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, F, B, G1, G2, E)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'Q'",
|
|
char: 'Q',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, F, B, E, L, C, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'R'",
|
|
char: 'R',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, F, B, G1, G2, E, L)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'S'",
|
|
char: 'S',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, F, G1, G2, C, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'T'",
|
|
char: 'T',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, J, M)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'U'",
|
|
char: 'U',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, F, B, E, C, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'V'",
|
|
char: 'V',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, F, K, E, N)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'W'",
|
|
char: 'W',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, F, E, N, L, C, B)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'X'",
|
|
char: 'X',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, H, K, N, L)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'Y'",
|
|
char: 'Y',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, F, B, G1, G2, C, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'Z'",
|
|
char: 'Z',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, A2, K, N, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '['",
|
|
char: '[',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A2, J, M, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '\\'",
|
|
char: '\\',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, H, L)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays ']'",
|
|
char: ']',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, J, M, D1)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '^'",
|
|
char: '^',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, N, L)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '_'",
|
|
char: '_',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '`'",
|
|
char: '`',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, H)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'a'",
|
|
char: 'a',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, G1, E, M, D1, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'b'",
|
|
char: 'b',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, F, G1, E, M, D1)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'c'",
|
|
char: 'c',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, G1, E, D1)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'd'",
|
|
char: 'd',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, B, G2, M, C, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'e'",
|
|
char: 'e',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, G1, E, N, D1)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'f'",
|
|
char: 'f',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A2, J, G1, G2, M)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'g'",
|
|
char: 'g',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, F, J, G1, M, D1)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'h'",
|
|
char: 'h',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, F, G1, E, M)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'i'",
|
|
char: 'i',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, M)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'j'",
|
|
char: 'j',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, J, E, M, D1)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'k'",
|
|
char: 'k',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, J, K, M, L)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'l'",
|
|
char: 'l',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, F, E)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'm'",
|
|
char: 'm',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, G1, G2, E, M, C)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'n'",
|
|
char: 'n',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, G1, E, M)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'o'",
|
|
char: 'o',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, G1, E, M, D1)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'p'",
|
|
char: 'p',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, F, J, G1, E)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'q'",
|
|
char: 'q',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, F, J, G1, M)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'r'",
|
|
char: 'r',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, G1, E)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 's'",
|
|
char: 's',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, F, G1, M, D1)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 't'",
|
|
char: 't',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, F, G1, E, D1)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'u'",
|
|
char: 'u',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, E, M, D1)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'v'",
|
|
char: 'v',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, E, N)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'w'",
|
|
char: 'w',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, E, N, L, C)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'x'",
|
|
char: 'x',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, H, K, N, L)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'y'",
|
|
char: 'y',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, J, B, G2, C, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays 'z'",
|
|
char: 'z',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, G1, N, D1)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '{'",
|
|
char: '{',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A2, J, G1, M, D2)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '|'",
|
|
char: '|',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, J, M)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '}'",
|
|
char: '}',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, A1, J, G2, M, D1)
|
|
},
|
|
},
|
|
{
|
|
desc: "displays '~'",
|
|
char: '~',
|
|
want: func(size image.Point) *faketerm.Terminal {
|
|
return mustDrawSegments(size, K, G1, G2, N)
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
d := New()
|
|
if tc.update != nil {
|
|
err := tc.update(d)
|
|
if err != nil {
|
|
t.Fatalf("tc.update => unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
{
|
|
err := d.SetCharacter(tc.char)
|
|
if (err != nil) != tc.wantErr {
|
|
t.Errorf("SetCharacter => unexpected error: %v, wantErr: %v", err, tc.wantErr)
|
|
}
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
ar := image.Rect(0, 0, segdisp.MinCols, segdisp.MinRows)
|
|
cvs, err := canvas.New(ar)
|
|
if err != nil {
|
|
t.Fatalf("canvas.New => unexpected error: %v", err)
|
|
}
|
|
|
|
if err := d.Draw(cvs); err != nil {
|
|
t.Fatalf("Draw => unexpected error: %v", err)
|
|
}
|
|
|
|
size := area.Size(ar)
|
|
want := faketerm.MustNew(size)
|
|
if tc.want != nil {
|
|
want = tc.want(size)
|
|
}
|
|
|
|
got, err := faketerm.New(size)
|
|
if err != nil {
|
|
t.Fatalf("faketerm.New => unexpected error: %v", err)
|
|
}
|
|
if err := cvs.Apply(got); err != nil {
|
|
t.Fatalf("bc.Apply => unexpected error: %v", err)
|
|
}
|
|
if diff := faketerm.Diff(want, got); diff != "" {
|
|
t.Fatalf("SetCharacter => %v", diff)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAllSegments(t *testing.T) {
|
|
want := []Segment{A1, A2, B, C, D1, D2, E, F, G1, G2, H, J, K, L, M, N}
|
|
got := AllSegments()
|
|
sort.Slice(got, func(i, j int) bool {
|
|
return int(got[i]) < int(got[j])
|
|
})
|
|
if diff := pretty.Compare(want, got); diff != "" {
|
|
t.Errorf("AllSegments => unexpected diff (-want, +got):\n%s", diff)
|
|
}
|
|
}
|
|
|
|
func TestSupportsChars(t *testing.T) {
|
|
tests := []struct {
|
|
desc string
|
|
str string
|
|
wantRes bool
|
|
wantUnsupp []rune
|
|
}{
|
|
{
|
|
desc: "supports all chars in an empty string",
|
|
wantRes: true,
|
|
},
|
|
{
|
|
desc: "supports all chars in the string",
|
|
str: " wW ",
|
|
wantRes: true,
|
|
},
|
|
{
|
|
desc: "supports some chars in the string",
|
|
str: " w←W :",
|
|
wantRes: false,
|
|
wantUnsupp: []rune{'←'},
|
|
},
|
|
{
|
|
desc: "supports no chars in the string",
|
|
str: "←",
|
|
wantRes: false,
|
|
wantUnsupp: []rune{'←'},
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
gotRes, gotUnsupp := SupportsChars(tc.str)
|
|
if gotRes != tc.wantRes {
|
|
t.Errorf("SupportsChars(%q) => %v, %v, want %v, %v", tc.str, gotRes, gotUnsupp, tc.wantRes, tc.wantUnsupp)
|
|
}
|
|
|
|
sort.Slice(gotUnsupp, func(i, j int) bool {
|
|
return gotUnsupp[i] < gotUnsupp[j]
|
|
})
|
|
sort.Slice(tc.wantUnsupp, func(i, j int) bool {
|
|
return tc.wantUnsupp[i] < tc.wantUnsupp[j]
|
|
})
|
|
if diff := pretty.Compare(tc.wantUnsupp, gotUnsupp); diff != "" {
|
|
t.Errorf("SupportsChars => unexpected unsupported characters returned, diff (-want, +got):\n%s", diff)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSanitize(t *testing.T) {
|
|
tests := []struct {
|
|
desc string
|
|
str string
|
|
want string
|
|
}{
|
|
{
|
|
desc: "no alternation to empty string",
|
|
},
|
|
{
|
|
desc: "all characters are supported",
|
|
str: " wW",
|
|
want: " wW",
|
|
},
|
|
{
|
|
desc: "some characters are supported",
|
|
str: " w←W:",
|
|
want: " w W:",
|
|
},
|
|
{
|
|
desc: "no characters are supported",
|
|
str: "←",
|
|
want: " ",
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
got := Sanitize(tc.str)
|
|
if got != tc.want {
|
|
t.Errorf("Sanitize => %q, want %q", got, tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|