Skip to content

Commit

Permalink
fixes #27 Add a test framework & test code
Browse files Browse the repository at this point in the history
  • Loading branch information
gdamore committed Oct 6, 2015
1 parent b19d706 commit 69be119
Show file tree
Hide file tree
Showing 6 changed files with 897 additions and 16 deletions.
50 changes: 34 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
[![Gitter](https://img.shields.io/badge/gitter-join-brightgreen.svg)](https://gitter.im/gdamore/tcell)
[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://godoc.org/github.com/gdamore/tcell)

> _Tcell is a work in progress (Beta).
> _Tcell is a work in progress (Gamma).
> Please use with caution; interfaces may change in before final release.
> That said, our confidence in Tcell's stability is increasing. If you
> would like to use it in your own application, it is recommended that
> you drop a message to garrett@damore.org before commitment._
Package tcell provides a cell based view for text terminals, like xterm.
It was inspired by termbox, but differs from termbox in some important
ways. It also adds signficant functionality beyond termbox.
ways. It also adds substantial functionality beyond termbox.

## Pure Go Terminfo Database

Expand Down Expand Up @@ -50,27 +50,36 @@ use with programs that use exec, or otherwise need to manipulate the
tty streams. This model is also much closer to idiomatic Go, leading
to fewer surprises.

## Richer Unicode support
## Richer Unicode & non-Unicode support

Tcell includes enhanced support for Unicode, include wide characters and
combining characters, provided your terminal can support them. Note that
Windows terminals generally don't support the full Unicode repertoire.

It will also convert to and from Unicode locales, so that the program
can work with UTF-8 internally, and get reasonable output in other locales.
We try hard to convert to native characters on both input and output, and
on output we even make use of the alternate character set to facilitate
drawing certain characters.

## More Function Keys

It also has richer support for a larger number of
special keys that some terminals can send.

## Better color handling

Tcell will respect your terminal's color space as specified within your terminfo
Tcell will respect your terminal's color space as specified within your terminfo
entries, so that for example attempts to emit color sequences on VT100 terminals
won't result in unintended consequences.

In Windows mode, we support 16 colors, underline, bold, dim, and reverse,
instead of just termbox's 8 colors with reverse. (Note that there is some
conflation with bold/dim and colors.)

Tcell maps 16 colors down to 8, for Terminals that need it. (The upper
8 colors are just brighter versions of the lower 8.)

## Better mouse support

It supports enhanced mouse tracking mode, so your application can receive
Expand All @@ -80,7 +89,8 @@ regular mouse motion events, and wheel events, if your terminal supports it.

I started this project originally by submitting patches to the author of
go-termbox, but due to some fundamental differences of opinion, I thought
it might be simpler just to start from scratch.
it might be simpler just to start from scratch. At this point, Tcell has
far exceeded the capabilities of termbox.

## Termbox compatibility

Expand All @@ -89,13 +99,14 @@ directory. To use it, try importing "github.com/gdamore/tcell/termbox"
instead. Most termbox-go programs will probably work without further
modification.

## Working with Unicode
## Working With Unicode

This version of the tcells expects that your terminal can support Unicode
on output. That is, if you submit Unicode sequences to it, it will attempt
send Unicode to the terminal. This works for modern xterm and other emulators,
but legacy systems may have poor results. I'm interested to hear reports from
folks who need support for other character sets.
Internally Tcell uses UTF-8, just like Go. However, it understands how to
convert to and from other character sets, using the capabilities of
the golang.org/x/text/encoding packages. Your application must supply
them, as the full set of the most common ones bloats the program by about
2MB. If you're lazy, and want them all anyway, see the tcell/encoding
sub package.

## Wide & Combining Characters

Expand All @@ -108,8 +119,7 @@ results are undefined. (Normally the wide character will not be displayed.)

Experience has shown that the vanilla Windows 8 console application does not
support any of these characters properly, but at least some options like
ConEmu do support Wide characters at least. Combining characters are
disabled for Windows in the release.
ConEmu do support Wide characters at least.

## Colors

Expand All @@ -125,9 +135,6 @@ know; it wouldn't be hard to add that if there is need.
Reasonable attempts have been made to minimize sending data to terminals,
avoiding repeated sequences or drawing the same cell on refresh updates.

Windows still needs some work here, as it can make numerous system calls
a bit less efficiently than it could.

## Terminfo

(Not relevent for Windows users.)
Expand Down Expand Up @@ -177,6 +184,13 @@ consoles, all support this quite nicely. On other platforms you might
find that only mouse click and release events are reported, with
no intervening motion events. It really depends on your terminal.

## Testablity

There is a SimulationScreen, that can be used to simulate a real screen
for automated testing. The supplied tests do this. The simulation contains
event delivery, screen resizing support, and capabilities to inject events
and examine "physical" screen contents.

## Platforms

On POSIX systems, a POSIX termios implementation with /dev/tty is required.
Expand All @@ -197,3 +211,7 @@ fully compatible consule implementation. We expect that Windows 10
ships with a less crippled implementation than prior releases -- we haven't
tested that, lacking Windows 10 ourselves.

The nacl and plan9 platforms won't work, but compilation stubs are supplied
for folks that want to include parts of this in software targetting those
platforms. The test screens will work, but as we don't know how to allocate
a real screen object on those platforms, NewScreen() will fail.
77 changes: 77 additions & 0 deletions event_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2015 The TCell Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use 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 tcell

import (
"testing"
"time"

. "github.com/smartystreets/goconvey/convey"
)

func eventLoop(s SimulationScreen, evch chan Event) {
for {
ev := s.PollEvent()
if ev == nil {
close(evch)
return
}
select {
case evch <- ev:
case <-time.After(time.Second):
}
}
}

func TestMouseEvents(t *testing.T) {

Convey("Mouse events", t, WithScreen(t, "", func(s SimulationScreen) {

Convey("Size should be valid", func() {
x, y := s.Size()
So(x, ShouldEqual, 80)
So(y, ShouldEqual, 25)
})

s.EnableMouse()
s.InjectMouse(4, 9, Button1, ModCtrl)
evch := make(chan Event)
em := &EventMouse{}
done := false
go eventLoop(s, evch)

for !done {
select {
case ev := <-evch:
if evm, ok := ev.(*EventMouse); ok {
em = evm
done = true
}
continue
case <-time.After(time.Second):
done = true
}
}
Convey("We got our mouse event", func() {
So(em, ShouldNotBeNil)
x, y := em.Position()
So(x, ShouldEqual, 4)
So(y, ShouldEqual, 9)
So(em.Buttons(), ShouldEqual, Button1)
So(em.Modifiers(), ShouldEqual, ModCtrl)
})
}))

}
151 changes: 151 additions & 0 deletions sim_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// Copyright 2015 The TCell Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use 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 tcell

import (
"testing"

. "github.com/smartystreets/goconvey/convey"
)

func WithScreen(t *testing.T, charset string, fn func(s SimulationScreen)) func() {
return func() {
s := NewSimulationScreen(charset)
So(s, ShouldNotBeNil)
e := s.Init()
So(e, ShouldBeNil)
Reset(func() {
s.Fini()
})
fn(s)
}
}

func TestInitScreen(t *testing.T) {

Convey("Init a screen", t, WithScreen(t, "", func(s SimulationScreen) {

Convey("Size should be valid", func() {
x, y := s.Size()
So(x, ShouldEqual, 80)
So(y, ShouldEqual, 25)
})

Convey("Default charset is UTF-8", func() {
So(s.CharacterSet(), ShouldEqual, "UTF-8")
})

Convey("Backing size is correct", func() {
b, x, y := s.GetContents()
So(b, ShouldNotBeNil)
So(x, ShouldEqual, 80)
So(y, ShouldEqual, 25)
So(len(b), ShouldEqual, x*y)
})
}))

}

func TestClearScreen(t *testing.T) {
Convey("Clear screen", t, WithScreen(t, "", func(s SimulationScreen) {

s.Clear()
b, x, y := s.GetContents()
So(b, ShouldNotBeNil)
So(x, ShouldEqual, 80)
So(y, ShouldEqual, 25)
So(len(b), ShouldEqual, x*y)
s.Sync()

nmatch := 0
for i := 0; i < x*y; i++ {
if len(b[i].Runes) == 0 {
nmatch++
}
}
So(nmatch, ShouldEqual, x*y)

nmatch = 0
for i := 0; i < x*y; i++ {
if len(b[i].Bytes) == 1 {
nmatch++
}
}
So(nmatch, ShouldEqual, x*y)

nmatch = 0
for i := 0; i < x*y; i++ {
if b[i].Style == StyleDefault {
nmatch++
}
}
So(nmatch, ShouldEqual, x*y)
So(b[0].Bytes[0], ShouldEqual, ' ')
}))
}

func TestSetCell(t *testing.T) {
st := StyleDefault.Background(ColorRed).Blink(true)
Convey("Set contents", t, WithScreen(t, "", func(s SimulationScreen) {
s.SetCell(2, 5, st, '@')
b, x, y := s.GetContents()
So(len(b), ShouldEqual, x*y)
So(x, ShouldEqual, 80)
So(y, ShouldEqual, 25)
s.Show()

sc := &b[5*80+2]
So(len(sc.Runes), ShouldEqual, 1)
So(len(sc.Bytes), ShouldEqual, 1)
So(sc.Bytes[0], ShouldEqual, '@')
So(sc.Runes[0], ShouldEqual, '@')
So(sc.Style, ShouldEqual, st)
}))
}

func TestResize(t *testing.T) {
st := StyleDefault.Background(ColorYellow).Underline(true)
Convey("Resize", t, WithScreen(t, "", func(s SimulationScreen) {
s.SetCell(2, 5, st, '&')
b, x, y := s.GetContents()
So(len(b), ShouldEqual, x*y)
So(x, ShouldEqual, 80)
So(y, ShouldEqual, 25)
s.Show()

sc := &b[5*80+2]
So(len(sc.Runes), ShouldEqual, 1)
So(len(sc.Bytes), ShouldEqual, 1)
So(sc.Bytes[0], ShouldEqual, '&')
So(sc.Runes[0], ShouldEqual, '&')
So(sc.Style, ShouldEqual, st)

Convey("Do resize", func() {
s.Resize(30, 10)
s.Show()
b2, x2, y2 := s.GetContents()
So(b2, ShouldNotEqual, b)
So(x2, ShouldEqual, 30)
So(y2, ShouldEqual, 10)

sc2 := &b[5*80+2]
So(len(sc2.Runes), ShouldEqual, 1)
So(len(sc2.Bytes), ShouldEqual, 1)
So(sc2.Bytes[0], ShouldEqual, '&')
So(sc2.Runes[0], ShouldEqual, '&')
So(sc2.Style, ShouldEqual, st)
})
}))
}
Loading

0 comments on commit 69be119

Please sign in to comment.