stario/io_test.go

235 lines
6.1 KiB
Go
Raw Normal View History

2022-03-18 13:49:38 +08:00
package stario
import (
"bufio"
"errors"
2022-03-18 13:49:38 +08:00
"fmt"
"strings"
2022-03-18 13:49:38 +08:00
"testing"
)
func installRawInputStub(t *testing.T, input string, signalErr error) {
t.Helper()
prevFactory := rawTerminalSessionFactory
prevSignalHandler := inputSignalHandler
rawTerminalSessionFactory = func(hint string, printNewline bool) (*rawTerminalSession, error) {
return &rawTerminalSession{
reader: bufio.NewReader(strings.NewReader(input)),
redrawHint: promptRedrawHint(hint),
}, nil
}
inputSignalHandler = func(sigtype rune) error {
return signalErr
}
t.Cleanup(func() {
rawTerminalSessionFactory = prevFactory
inputSignalHandler = prevSignalHandler
})
}
2026-03-21 19:15:43 +08:00
func TestPromptRedrawHint(t *testing.T) {
got := promptRedrawHint("头部提示\n 中文确认: ")
if got != "中文确认:" {
t.Fatalf("unexpected redraw hint: got %q", got)
}
}
func TestStringDisplayWidth(t *testing.T) {
got := stringDisplayWidth("中a[]")
if got != 5 {
t.Fatalf("unexpected display width: got %d want 5", got)
}
}
func TestRawEchoRenderUnitPlainRune(t *testing.T) {
text, width, ok := rawEchoRenderUnit('中', "", 0)
if !ok {
t.Fatal("expected plain wide rune to use fast path")
}
if text != "中" || width != 2 {
t.Fatalf("unexpected render unit: got (%q, %d) want (%q, %d)", text, width, "中", 2)
}
}
func TestRawEchoRenderUnitMaskedRune(t *testing.T) {
text, width, ok := rawEchoRenderUnit('a', "[]", stringDisplayWidth("[]"))
if !ok {
t.Fatal("expected masked rune to use fast path")
}
if text != "[]" || width != 2 {
t.Fatalf("unexpected render unit: got (%q, %d) want (%q, %d)", text, width, "[]", 2)
}
}
func TestRawEchoRenderUnitFallsBackForControlRune(t *testing.T) {
if _, _, ok := rawEchoRenderUnit('\x00', "", 0); ok {
t.Fatal("expected control rune to fall back to full redraw")
}
}
func TestSignalInputResultExitSuppressesError(t *testing.T) {
got := signalInputResult(rawInputSignalExit, ErrSignalInterrupt)
if got.err != nil {
t.Fatalf("expected nil error, got %v", got.err)
}
if got.msg != "" {
t.Fatalf("expected empty message, got %q", got.msg)
}
}
func TestSignalInputResultReturnErrorPreservesSignal(t *testing.T) {
got := signalInputResult(rawInputSignalReturnError, ErrSignalInterrupt)
if !errors.Is(got.err, ErrSignalInterrupt) {
t.Fatalf("expected signal error, got %v", got.err)
}
if got.msg != "" {
t.Fatalf("expected empty message, got %q", got.msg)
}
}
func TestPasswdSuppressesSignalError(t *testing.T) {
installRawInputStub(t, string([]rune{0x03}), ErrSignalInterrupt)
got := Passwd("", "fallback")
if got.err != nil {
t.Fatalf("expected nil error, got %v", got.err)
}
if got.msg != "" {
t.Fatalf("expected empty message after signal exit, got %q", got.msg)
}
}
func TestPasswdResponseSignalPreservesSignalError(t *testing.T) {
installRawInputStub(t, string([]rune{0x03}), ErrSignalInterrupt)
got := PasswdResponseSignal("", "fallback")
if !errors.Is(got.err, ErrSignalInterrupt) {
t.Fatalf("expected interrupt error, got %v", got.err)
}
if got.msg != "" {
t.Fatalf("expected empty message after signal exit, got %q", got.msg)
}
}
func TestStopUntilEmptyTriggerReturnsAfterFirstKey(t *testing.T) {
installRawInputStub(t, "abc", nil)
if err := StopUntil("", "", false); err != nil {
t.Fatalf("StopUntil returned error: %v", err)
}
}
2026-03-21 19:15:43 +08:00
func TestParseYesNoValue(t *testing.T) {
cases := []struct {
name string
input string
defaults bool
want bool
ok bool
}{
{name: "default", input: " ", defaults: true, want: true, ok: true},
{name: "yes", input: "yes", defaults: false, want: true, ok: true},
{name: "no", input: "No", defaults: true, want: false, ok: true},
{name: "invalid", input: "maybe", defaults: false, want: false, ok: false},
}
for _, tc := range cases {
got, ok := parseYesNoValue(tc.input, tc.defaults)
if got != tc.want || ok != tc.ok {
t.Fatalf("%s: got (%v, %v) want (%v, %v)", tc.name, got, ok, tc.want, tc.ok)
}
}
}
func TestSliceFloat32(t *testing.T) {
data := InputMsg{msg: "1.5,2.25", err: nil}
got, err := data.SliceFloat32(",")
if err != nil {
t.Fatalf("SliceFloat32 returned error: %v", err)
}
if len(got) != 2 || got[0] != float32(1.5) || got[1] != float32(2.25) {
t.Fatalf("unexpected float32 slice: %#v", got)
}
}
func TestTypedSliceParsingTrimsTokenWhitespace(t *testing.T) {
ints, err := (InputMsg{msg: "1, 2, 3"}).SliceInt(",")
if err != nil {
t.Fatalf("SliceInt returned error: %v", err)
}
if len(ints) != 3 || ints[0] != 1 || ints[1] != 2 || ints[2] != 3 {
t.Fatalf("unexpected int slice: %#v", ints)
}
bools, err := (InputMsg{msg: "true, false, true"}).SliceBool(",")
if err != nil {
t.Fatalf("SliceBool returned error: %v", err)
}
if len(bools) != 3 || !bools[0] || bools[1] || !bools[2] {
t.Fatalf("unexpected bool slice: %#v", bools)
}
float64s, err := (InputMsg{msg: "1.25, 2.5, 3.75"}).SliceFloat64(",")
if err != nil {
t.Fatalf("SliceFloat64 returned error: %v", err)
}
if len(float64s) != 3 || float64s[0] != 1.25 || float64s[1] != 2.5 || float64s[2] != 3.75 {
t.Fatalf("unexpected float64 slice: %#v", float64s)
}
}
func TestAdvanceTriggerIndexHandlesOverlap(t *testing.T) {
trigger := []rune("aba")
prefix := buildTriggerPrefixTable(trigger)
index := 0
complete := false
for _, r := range []rune("aaba") {
index, complete = advanceTriggerIndex(trigger, prefix, index, r)
if complete {
break
}
}
if !complete {
t.Fatal("expected overlapped trigger to complete")
}
}
2022-03-18 13:49:38 +08:00
func Test_Slice(t *testing.T) {
var data = InputMsg{
msg: "true,false,true,true,false,0,1,hello",
err: nil,
skipSliceSigErr: false,
}
res, err := data.IgnoreSliceParseError(true).SliceBool(",")
if err != nil {
fmt.Println(res)
t.Fatal(err)
}
if len(res) == 0 {
t.Fatal(res)
}
fmt.Println(res)
}
func TestSliceMsg(t *testing.T) {
var data = InputMsg{
msg: "",
err: nil,
skipSliceSigErr: false,
}
res, err := data.SliceString(",")
if err != nil {
fmt.Println(res)
t.Fatal(err)
}
if len(res) != 0 {
t.Fatal(res)
}
fmt.Println(len(res))
res2, err := data.SliceInt64(",")
if err != nil {
fmt.Println(res2)
t.Fatal(err)
}
if len(res2) != 0 {
t.Fatal(res2)
}
fmt.Println(len(res2))
}