Make special keys case insensitive.

add tests
This commit is contained in:
Matthew Hooker 2018-04-13 14:41:17 -07:00
parent cba4d3235f
commit e2e7bc65fd
No known key found for this signature in database
GPG Key ID: 7B5F933D9CE8C6A1
8 changed files with 263 additions and 129 deletions

View File

@ -222,39 +222,39 @@ var g = &grammar{
},
{
name: "Number",
pos: position{line: 38, col: 1, offset: 799},
pos: position{line: 39, col: 1, offset: 810},
expr: &actionExpr{
pos: position{line: 38, col: 10, offset: 808},
pos: position{line: 39, col: 10, offset: 819},
run: (*parser).callonNumber1,
expr: &seqExpr{
pos: position{line: 38, col: 10, offset: 808},
pos: position{line: 39, col: 10, offset: 819},
exprs: []interface{}{
&zeroOrOneExpr{
pos: position{line: 38, col: 10, offset: 808},
pos: position{line: 39, col: 10, offset: 819},
expr: &litMatcher{
pos: position{line: 38, col: 10, offset: 808},
pos: position{line: 39, col: 10, offset: 819},
val: "-",
ignoreCase: false,
},
},
&ruleRefExpr{
pos: position{line: 38, col: 15, offset: 813},
pos: position{line: 39, col: 15, offset: 824},
name: "Integer",
},
&zeroOrOneExpr{
pos: position{line: 38, col: 23, offset: 821},
pos: position{line: 39, col: 23, offset: 832},
expr: &seqExpr{
pos: position{line: 38, col: 25, offset: 823},
pos: position{line: 39, col: 25, offset: 834},
exprs: []interface{}{
&litMatcher{
pos: position{line: 38, col: 25, offset: 823},
pos: position{line: 39, col: 25, offset: 834},
val: ".",
ignoreCase: false,
},
&oneOrMoreExpr{
pos: position{line: 38, col: 29, offset: 827},
pos: position{line: 39, col: 29, offset: 838},
expr: &ruleRefExpr{
pos: position{line: 38, col: 29, offset: 827},
pos: position{line: 39, col: 29, offset: 838},
name: "Digit",
},
},
@ -267,29 +267,29 @@ var g = &grammar{
},
{
name: "Integer",
pos: position{line: 42, col: 1, offset: 873},
pos: position{line: 43, col: 1, offset: 884},
expr: &choiceExpr{
pos: position{line: 42, col: 11, offset: 883},
pos: position{line: 43, col: 11, offset: 894},
alternatives: []interface{}{
&litMatcher{
pos: position{line: 42, col: 11, offset: 883},
pos: position{line: 43, col: 11, offset: 894},
val: "0",
ignoreCase: false,
},
&actionExpr{
pos: position{line: 42, col: 17, offset: 889},
pos: position{line: 43, col: 17, offset: 900},
run: (*parser).callonInteger3,
expr: &seqExpr{
pos: position{line: 42, col: 17, offset: 889},
pos: position{line: 43, col: 17, offset: 900},
exprs: []interface{}{
&ruleRefExpr{
pos: position{line: 42, col: 17, offset: 889},
pos: position{line: 43, col: 17, offset: 900},
name: "NonZeroDigit",
},
&zeroOrMoreExpr{
pos: position{line: 42, col: 30, offset: 902},
pos: position{line: 43, col: 30, offset: 913},
expr: &ruleRefExpr{
pos: position{line: 42, col: 30, offset: 902},
pos: position{line: 43, col: 30, offset: 913},
name: "Digit",
},
},
@ -301,21 +301,21 @@ var g = &grammar{
},
{
name: "Duration",
pos: position{line: 46, col: 1, offset: 966},
pos: position{line: 47, col: 1, offset: 977},
expr: &actionExpr{
pos: position{line: 46, col: 12, offset: 977},
pos: position{line: 47, col: 12, offset: 988},
run: (*parser).callonDuration1,
expr: &oneOrMoreExpr{
pos: position{line: 46, col: 12, offset: 977},
pos: position{line: 47, col: 12, offset: 988},
expr: &seqExpr{
pos: position{line: 46, col: 14, offset: 979},
pos: position{line: 47, col: 14, offset: 990},
exprs: []interface{}{
&ruleRefExpr{
pos: position{line: 46, col: 14, offset: 979},
pos: position{line: 47, col: 14, offset: 990},
name: "Number",
},
&ruleRefExpr{
pos: position{line: 46, col: 21, offset: 986},
pos: position{line: 47, col: 21, offset: 997},
name: "TimeUnit",
},
},
@ -325,12 +325,12 @@ var g = &grammar{
},
{
name: "On",
pos: position{line: 50, col: 1, offset: 1049},
pos: position{line: 51, col: 1, offset: 1060},
expr: &actionExpr{
pos: position{line: 50, col: 6, offset: 1054},
pos: position{line: 51, col: 6, offset: 1065},
run: (*parser).callonOn1,
expr: &litMatcher{
pos: position{line: 50, col: 6, offset: 1054},
pos: position{line: 51, col: 6, offset: 1065},
val: "on",
ignoreCase: true,
},
@ -338,12 +338,12 @@ var g = &grammar{
},
{
name: "Off",
pos: position{line: 54, col: 1, offset: 1087},
pos: position{line: 55, col: 1, offset: 1098},
expr: &actionExpr{
pos: position{line: 54, col: 7, offset: 1093},
pos: position{line: 55, col: 7, offset: 1104},
run: (*parser).callonOff1,
expr: &litMatcher{
pos: position{line: 54, col: 7, offset: 1093},
pos: position{line: 55, col: 7, offset: 1104},
val: "off",
ignoreCase: true,
},
@ -351,216 +351,216 @@ var g = &grammar{
},
{
name: "Literal",
pos: position{line: 58, col: 1, offset: 1128},
pos: position{line: 59, col: 1, offset: 1139},
expr: &actionExpr{
pos: position{line: 58, col: 11, offset: 1138},
pos: position{line: 59, col: 11, offset: 1149},
run: (*parser).callonLiteral1,
expr: &anyMatcher{
line: 58, col: 11, offset: 1138,
line: 59, col: 11, offset: 1149,
},
},
},
{
name: "ExprEnd",
pos: position{line: 63, col: 1, offset: 1219},
pos: position{line: 64, col: 1, offset: 1230},
expr: &litMatcher{
pos: position{line: 63, col: 11, offset: 1229},
pos: position{line: 64, col: 11, offset: 1240},
val: ">",
ignoreCase: false,
},
},
{
name: "ExprStart",
pos: position{line: 64, col: 1, offset: 1233},
pos: position{line: 65, col: 1, offset: 1244},
expr: &litMatcher{
pos: position{line: 64, col: 13, offset: 1245},
pos: position{line: 65, col: 13, offset: 1256},
val: "<",
ignoreCase: false,
},
},
{
name: "SpecialKey",
pos: position{line: 65, col: 1, offset: 1249},
pos: position{line: 66, col: 1, offset: 1260},
expr: &choiceExpr{
pos: position{line: 65, col: 14, offset: 1262},
pos: position{line: 66, col: 14, offset: 1273},
alternatives: []interface{}{
&litMatcher{
pos: position{line: 65, col: 14, offset: 1262},
pos: position{line: 66, col: 14, offset: 1273},
val: "bs",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 65, col: 22, offset: 1270},
pos: position{line: 66, col: 22, offset: 1281},
val: "del",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 65, col: 31, offset: 1279},
pos: position{line: 66, col: 31, offset: 1290},
val: "enter",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 65, col: 42, offset: 1290},
pos: position{line: 66, col: 42, offset: 1301},
val: "esc",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 65, col: 51, offset: 1299},
pos: position{line: 66, col: 51, offset: 1310},
val: "f10",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 65, col: 60, offset: 1308},
pos: position{line: 66, col: 60, offset: 1319},
val: "f11",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 65, col: 69, offset: 1317},
pos: position{line: 66, col: 69, offset: 1328},
val: "f12",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 66, col: 11, offset: 1334},
pos: position{line: 67, col: 11, offset: 1345},
val: "f1",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 66, col: 19, offset: 1342},
pos: position{line: 67, col: 19, offset: 1353},
val: "f2",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 66, col: 27, offset: 1350},
pos: position{line: 67, col: 27, offset: 1361},
val: "f3",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 66, col: 35, offset: 1358},
pos: position{line: 67, col: 35, offset: 1369},
val: "f4",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 66, col: 43, offset: 1366},
pos: position{line: 67, col: 43, offset: 1377},
val: "f5",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 66, col: 51, offset: 1374},
pos: position{line: 67, col: 51, offset: 1385},
val: "f6",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 66, col: 59, offset: 1382},
pos: position{line: 67, col: 59, offset: 1393},
val: "f7",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 66, col: 67, offset: 1390},
pos: position{line: 67, col: 67, offset: 1401},
val: "f8",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 66, col: 75, offset: 1398},
pos: position{line: 67, col: 75, offset: 1409},
val: "f9",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 67, col: 12, offset: 1415},
pos: position{line: 68, col: 12, offset: 1426},
val: "return",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 67, col: 24, offset: 1427},
pos: position{line: 68, col: 24, offset: 1438},
val: "tab",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 67, col: 33, offset: 1436},
pos: position{line: 68, col: 33, offset: 1447},
val: "up",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 67, col: 41, offset: 1444},
pos: position{line: 68, col: 41, offset: 1455},
val: "down",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 67, col: 51, offset: 1454},
pos: position{line: 68, col: 51, offset: 1465},
val: "spacebar",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 67, col: 65, offset: 1468},
pos: position{line: 68, col: 65, offset: 1479},
val: "insert",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 67, col: 77, offset: 1480},
pos: position{line: 68, col: 77, offset: 1491},
val: "home",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 68, col: 11, offset: 1498},
pos: position{line: 69, col: 11, offset: 1509},
val: "end",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 68, col: 20, offset: 1507},
pos: position{line: 69, col: 20, offset: 1518},
val: "pageup",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 68, col: 32, offset: 1519},
pos: position{line: 69, col: 32, offset: 1530},
val: "pagedown",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 68, col: 46, offset: 1533},
pos: position{line: 69, col: 46, offset: 1544},
val: "leftalt",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 68, col: 59, offset: 1546},
pos: position{line: 69, col: 59, offset: 1557},
val: "leftctrl",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 68, col: 73, offset: 1560},
pos: position{line: 69, col: 73, offset: 1571},
val: "leftshift",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 69, col: 11, offset: 1583},
pos: position{line: 70, col: 11, offset: 1594},
val: "rightalt",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 69, col: 25, offset: 1597},
pos: position{line: 70, col: 25, offset: 1608},
val: "rightctrl",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 69, col: 40, offset: 1612},
pos: position{line: 70, col: 40, offset: 1623},
val: "rightshift",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 69, col: 56, offset: 1628},
pos: position{line: 70, col: 56, offset: 1639},
val: "leftsuper",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 69, col: 71, offset: 1643},
pos: position{line: 70, col: 71, offset: 1654},
val: "rightsuper",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 70, col: 11, offset: 1667},
pos: position{line: 71, col: 11, offset: 1678},
val: "left",
ignoreCase: true,
},
&litMatcher{
pos: position{line: 70, col: 21, offset: 1677},
pos: position{line: 71, col: 21, offset: 1688},
val: "right",
ignoreCase: true,
},
@ -569,9 +569,9 @@ var g = &grammar{
},
{
name: "NonZeroDigit",
pos: position{line: 72, col: 1, offset: 1687},
pos: position{line: 73, col: 1, offset: 1698},
expr: &charClassMatcher{
pos: position{line: 72, col: 16, offset: 1702},
pos: position{line: 73, col: 16, offset: 1713},
val: "[1-9]",
ranges: []rune{'1', '9'},
ignoreCase: false,
@ -580,9 +580,9 @@ var g = &grammar{
},
{
name: "Digit",
pos: position{line: 73, col: 1, offset: 1708},
pos: position{line: 74, col: 1, offset: 1719},
expr: &charClassMatcher{
pos: position{line: 73, col: 9, offset: 1716},
pos: position{line: 74, col: 9, offset: 1727},
val: "[0-9]",
ranges: []rune{'0', '9'},
ignoreCase: false,
@ -591,42 +591,42 @@ var g = &grammar{
},
{
name: "TimeUnit",
pos: position{line: 74, col: 1, offset: 1722},
pos: position{line: 75, col: 1, offset: 1733},
expr: &choiceExpr{
pos: position{line: 74, col: 13, offset: 1734},
pos: position{line: 75, col: 13, offset: 1745},
alternatives: []interface{}{
&litMatcher{
pos: position{line: 74, col: 13, offset: 1734},
pos: position{line: 75, col: 13, offset: 1745},
val: "ns",
ignoreCase: false,
},
&litMatcher{
pos: position{line: 74, col: 20, offset: 1741},
pos: position{line: 75, col: 20, offset: 1752},
val: "us",
ignoreCase: false,
},
&litMatcher{
pos: position{line: 74, col: 27, offset: 1748},
pos: position{line: 75, col: 27, offset: 1759},
val: "µs",
ignoreCase: false,
},
&litMatcher{
pos: position{line: 74, col: 34, offset: 1756},
pos: position{line: 75, col: 34, offset: 1767},
val: "ms",
ignoreCase: false,
},
&litMatcher{
pos: position{line: 74, col: 41, offset: 1763},
pos: position{line: 75, col: 41, offset: 1774},
val: "s",
ignoreCase: false,
},
&litMatcher{
pos: position{line: 74, col: 47, offset: 1769},
pos: position{line: 75, col: 47, offset: 1780},
val: "m",
ignoreCase: false,
},
&litMatcher{
pos: position{line: 74, col: 53, offset: 1775},
pos: position{line: 75, col: 53, offset: 1786},
val: "h",
ignoreCase: false,
},
@ -636,11 +636,11 @@ var g = &grammar{
{
name: "_",
displayName: "\"whitespace\"",
pos: position{line: 76, col: 1, offset: 1781},
pos: position{line: 77, col: 1, offset: 1792},
expr: &zeroOrMoreExpr{
pos: position{line: 76, col: 19, offset: 1799},
pos: position{line: 77, col: 19, offset: 1810},
expr: &charClassMatcher{
pos: position{line: 76, col: 19, offset: 1799},
pos: position{line: 77, col: 19, offset: 1810},
val: "[ \\n\\t\\r]",
chars: []rune{' ', '\n', '\t', '\r'},
ignoreCase: false,
@ -650,11 +650,11 @@ var g = &grammar{
},
{
name: "EOF",
pos: position{line: 78, col: 1, offset: 1811},
pos: position{line: 79, col: 1, offset: 1822},
expr: &notExpr{
pos: position{line: 78, col: 8, offset: 1818},
pos: position{line: 79, col: 8, offset: 1829},
expr: &anyMatcher{
line: 78, col: 9, offset: 1819,
line: 79, col: 9, offset: 1830,
},
},
},
@ -711,10 +711,11 @@ func (p *parser) callonCharToggle1() (interface{}, error) {
}
func (c *current) onSpecial1(s, t interface{}) (interface{}, error) {
l := strings.ToLower(string(s.([]byte)))
if t == nil {
return &specialExpression{string(s.([]byte)), KeyPress}, nil
return &specialExpression{l, KeyPress}, nil
}
return &specialExpression{string(s.([]byte)), t.(KeyAction)}, nil
return &specialExpression{l, t.(KeyAction)}, nil
}
func (p *parser) callonSpecial1() (interface{}, error) {

View File

@ -29,10 +29,11 @@ CharToggle = ExprStart lit:(Literal) t:(On / Off) ExprEnd {
}
Special = ExprStart s:(SpecialKey) t:(On / Off)? ExprEnd {
l := strings.ToLower(string(s.([]byte)))
if t == nil {
return &specialExpression{string(s.([]byte)), KeyPress}, nil
return &specialExpression{l, KeyPress}, nil
}
return &specialExpression{string(s.([]byte)), t.(KeyAction)}, nil
return &specialExpression{l, t.(KeyAction)}, nil
}
Number = '-'? Integer ( '.' Digit+ )? {

View File

@ -12,7 +12,6 @@ import (
TODO:
* tests
* fix vbox tests
* lower-case specials
* pc-at abstraction
* check that `<del>` works. It's different now.
* parallels

View File

@ -1,9 +1,12 @@
package bootcommand
import (
"fmt"
"log"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
func toIfaceSlice(v interface{}) []interface{} {
@ -13,18 +16,86 @@ func toIfaceSlice(v interface{}) []interface{} {
return v.([]interface{})
}
func TestParse(t *testing.T) {
func Test_parse(t *testing.T) {
in := "<wait><wait20><wait3s><wait4m2ns>"
in += "foo/bar > one 界"
in += "<fOn> b<fOff>"
in += "<fon> b<fOff>"
in += "<foo><f3><f12><spacebar><leftalt><rightshift><rightsuper>"
expected := []string{
"Wait<1s>",
"Wait<20s>",
"Wait<3s>",
"Wait<4m0.000000002s>",
"LIT-Press(f)",
"LIT-Press(o)",
"LIT-Press(o)",
"LIT-Press(/)",
"LIT-Press(b)",
"LIT-Press(a)",
"LIT-Press(r)",
"LIT-Press( )",
"LIT-Press(>)",
"LIT-Press( )",
"LIT-Press(o)",
"LIT-Press(n)",
"LIT-Press(e)",
"LIT-Press( )",
"LIT-Press(界)",
"LIT-On(f)",
"LIT-Press( )",
"LIT-Press(b)",
"LIT-Off(f)",
"LIT-Press(<)",
"LIT-Press(f)",
"LIT-Press(o)",
"LIT-Press(o)",
"LIT-Press(>)",
"Spec-Press(f3)",
"Spec-Press(f12)",
"Spec-Press(spacebar)",
"Spec-Press(leftalt)",
"Spec-Press(rightshift)",
"Spec-Press(rightsuper)",
}
got, err := ParseReader("", strings.NewReader(in))
if err != nil {
log.Fatal(err)
}
gL := toIfaceSlice(got)
for _, g := range gL {
for i, g := range gL {
assert.Equal(t, expected[i], fmt.Sprintf("%s", g))
log.Printf("%s\n", g)
}
}
func Test_special(t *testing.T) {
var specials = []struct {
in string
out string
}{
{
"<rightShift><rightshift><RIGHTSHIFT>",
"Spec-Press(rightshift)",
},
{
"<delon><delON><deLoN><DELON>",
"Spec-On(del)",
},
{
"<enteroff><enterOFF><eNtErOfF><ENTEROFF>",
"Spec-Off(enter)",
},
}
for _, tt := range specials {
got, err := ParseReader("", strings.NewReader(tt.in))
if err != nil {
log.Fatal(err)
}
gL := toIfaceSlice(got)
for _, g := range gL {
assert.Equal(t, tt.out, g.(*specialExpression).String())
}
}
}

View File

@ -67,16 +67,16 @@ func NewPCATDriver(send SendCodeFunc, chunkSize int) *pcATDriver {
sMap["insert"] = []string{"e052", "e0d2"}
sMap["home"] = []string{"e047", "e0c7"}
sMap["end"] = []string{"e04f", "e0cf"}
sMap["pageUp"] = []string{"e049", "e0c9"}
sMap["pageDown"] = []string{"e051", "e0d1"}
sMap["leftAlt"] = []string{"38", "b8"}
sMap["leftCtrl"] = []string{"1d", "9d"}
sMap["leftShift"] = []string{"2a", "aa"}
sMap["rightAlt"] = []string{"e038", "e0b8"}
sMap["rightCtrl"] = []string{"e01d", "e09d"}
sMap["rightShift"] = []string{"36", "b6"}
sMap["leftSuper"] = []string{"e05b", "e0db"}
sMap["rightSuper"] = []string{"e05c", "e0dc"}
sMap["pageup"] = []string{"e049", "e0c9"}
sMap["pagedown"] = []string{"e051", "e0d1"}
sMap["leftalt"] = []string{"38", "b8"}
sMap["leftctrl"] = []string{"1d", "9d"}
sMap["leftshift"] = []string{"2a", "aa"}
sMap["rightalt"] = []string{"e038", "e0b8"}
sMap["rightctrl"] = []string{"e01d", "e09d"}
sMap["rightshift"] = []string{"36", "b6"}
sMap["leftsuper"] = []string{"e05b", "e0db"}
sMap["rightsuper"] = []string{"e05c", "e0dc"}
scancodeIndex := make(map[string]byte)
scancodeIndex["1234567890-="] = 0x02

View File

@ -1,7 +1,11 @@
package bootcommand
import "testing"
import "github.com/stretchr/testify/assert"
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
)
func Test_chunkScanCodes(t *testing.T) {
@ -66,3 +70,19 @@ func Test_chunkScanCodeError(t *testing.T) {
_, err := chunkScanCodes(in, 2)
assert.Error(t, err)
}
func Test_pcatSpecialLookup(t *testing.T) {
in := "<rightShift><rightshiftoff><RIGHTSHIFTON>"
expected := []string{"36", "b6", "b6", "36"}
var codes []string
sendCodes := func(c []string) error {
codes = c
return nil
}
d := NewPCATDriver(sendCodes, -1)
seq, err := GenerateExpressionSequence(in)
assert.NoError(t, err)
err = seq.Do(context.Background(), d)
assert.NoError(t, err)
assert.Equal(t, expected, codes)
}

View File

@ -9,20 +9,23 @@ import (
"unicode"
"github.com/hashicorp/packer/common"
vnc "github.com/mitchellh/go-vnc"
)
const KeyLeftShift uint32 = 0xFFE1
type VNCKeyEvent interface {
KeyEvent(uint32, bool) error
}
type vncDriver struct {
c *vnc.ClientConn
c VNCKeyEvent
interval time.Duration
specialMap map[string]uint32
// keyEvent can set this error which will prevent it from continuing
err error
}
func NewVNCDriver(c *vnc.ClientConn) *vncDriver {
func NewVNCDriver(c VNCKeyEvent) *vncDriver {
// We delay (default 100ms) between each key event to allow for CPU or
// network latency. See PackerKeyEnv for tuning.
keyInterval := common.PackerKeyDefault
@ -58,16 +61,16 @@ func NewVNCDriver(c *vnc.ClientConn) *vncDriver {
sMap["insert"] = 0xFF63
sMap["home"] = 0xFF50
sMap["end"] = 0xFF57
sMap["pageUp"] = 0xFF55
sMap["pageDown"] = 0xFF56
sMap["leftAlt"] = 0xFFE9
sMap["leftCtrl"] = 0xFFE3
sMap["leftShift"] = 0xFFE1
sMap["rightAlt"] = 0xFFEA
sMap["rightCtrl"] = 0xFFE4
sMap["rightShift"] = 0xFFE2
sMap["leftSuper"] = 0xFFEB
sMap["rightSuper"] = 0xFFEC
sMap["pageup"] = 0xFF55
sMap["pagedown"] = 0xFF56
sMap["leftalt"] = 0xFFE9
sMap["leftctrl"] = 0xFFE3
sMap["leftshift"] = 0xFFE1
sMap["leftsuper"] = 0xFFEB
sMap["rightalt"] = 0xFFEA
sMap["rightctrl"] = 0xFFE4
sMap["rightshift"] = 0xFFE2
sMap["rightsuper"] = 0xFFEC
return &vncDriver{
c: c,

View File

@ -0,0 +1,39 @@
package bootcommand
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
)
type event struct {
u uint32
down bool
}
type sender struct {
e []event
}
func (s *sender) KeyEvent(u uint32, down bool) error {
s.e = append(s.e, event{u, down})
return nil
}
func Test_vncSpecialLookup(t *testing.T) {
in := "<rightShift><rightshiftoff><RIGHTSHIFTON>"
expected := []event{
{0xFFE2, true},
{0xFFE2, false},
{0xFFE2, false},
{0xFFE2, true},
}
s := &sender{}
d := NewVNCDriver(s)
seq, err := GenerateExpressionSequence(in)
assert.NoError(t, err)
err = seq.Do(context.Background(), d)
assert.NoError(t, err)
assert.Equal(t, expected, s.e)
}