Skip to content

Commit 29ab171

Browse files
MGTK: Add automation interface
Add a mechanism for test automation to interact directly with MGTK, allowing queries like "how many windows are open?", "what is the name of the top-most window?", and "where is the top-most window's title bar?" Since the MGTK API is relatively stable this is a safe integration point. Several tests updated to take advantage of this, but more can be done.
1 parent 2478ccf commit 29ab171

19 files changed

+568
-68
lines changed

src/mgtk/MGTK.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,3 +1349,26 @@ _DA specific:_
13491349
_DA specific:_
13501350

13511351
* Following a window move, resize or close, call `JUMP_TABLE_CLEAR_UPDATES` to allow DeskTop to handle update events. This will not redraw the DA window, however.
1352+
1353+
# Automation
1354+
1355+
MGTK exposes an automation interface, intended for use by automated tests. It works as follows:
1356+
1357+
* Wait for the keyboard strobe to be cleared. (`KBD` high bit off)
1358+
* Depress both Open Apple (`BUTN0`) and Solid Apple (`BUTN1`)
1359+
* Submit a keypress of ASCII `NUL` (Ctrl+Shift+2 on the Apple II keyboard)
1360+
* Wait for the keyboard strobe to be cleared.
1361+
* Release both Open Apple (`BUTN0`) and Solid Apple (`BUTN1`)
1362+
* Save copies of any bytes that will be modified by the following.
1363+
* Store any "in" call parameters into memory. (`$0003` is a good location)
1364+
* Set memory address `$0000` to the MGTK call number, and `$0001`/`$0002` to the address of parameter data.
1365+
* Submit any keypress.
1366+
* Wait for the keyboard strobe to be cleared.
1367+
* Read the call result from address `$00`.
1368+
* Load any "out" call parameters from memory.
1369+
* Submit any keypress.
1370+
* Wait for the keyboard strobe to be cleared.
1371+
1372+
Note that addresses assume the banking that this MGTK instance is running with. DeskTop normally runs with the Aux ZP active and MGTK-visible resoures like window titles in Aux or Aux LC memory. The Selector module has an MGTK instance in main memory and runs with the Main ZP active except for the alert code which resizes in the Aux LC bank.
1373+
1374+
Automation can use this interface to query for open windows and inspect their properties.

src/mgtk/mgtk.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,7 @@ event_modifier_solid_apple = 1 << 1
692692

693693
;;; Used in FindControl
694694
.enum Part
695+
inactive = 0
695696
up_arrow = 1
696697
left_arrow = 1
697698
down_arrow = 2

src/mgtk/mgtk.s

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5463,6 +5463,10 @@ irq_entry:
54635463
sta input::key
54645464
bit KBDSTRB ; clear strobe
54655465

5466+
;; Check if automation hook
5467+
jsr CheckAutomationHook
5468+
bcc end
5469+
54665470
;; Check if "MouseKeys" mode should be activated
54675471
jsr CheckActivateMouseKeys
54685472
bcc end
@@ -9884,6 +9888,37 @@ scale_y:
98849888
.endproc ; GetKey
98859889

98869890

9891+
.proc CheckAutomationHook
9892+
;; Check for OA+SA+Ctrl+Shift+2
9893+
lda input::modifiers
9894+
cmp #3
9895+
bne ignore
9896+
lda input::key
9897+
cmp #0 ; Ctrl-@
9898+
bne ignore
9899+
9900+
jsr wait_for_key
9901+
9902+
COPY_BYTES 3, $00, params
9903+
9904+
jsr SaveParamsAndStack ; restored by call below
9905+
jsr MGTKEntry
9906+
params: .res 3
9907+
sta $00
9908+
jsr RestoreParamsAndStack
9909+
9910+
FALL_THROUGH_TO wait_for_key
9911+
wait_for_key:
9912+
: lda KBD
9913+
bpl :-
9914+
sta KBDSTRB
9915+
RETURN C=0
9916+
9917+
ignore:
9918+
RETURN C=1
9919+
.endproc ; CheckAutomationHook
9920+
9921+
98879922
;;; Assert: `kbd_mouse_state` is not `kKeyboardMouseStateInactive`
98889923
.proc HandleKeyboardMouse
98899924
cmp #kKeyboardMouseStateMouseKeys

tests/apple_menu.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ test.Step(
5858
test.Snap("verify alert shown")
5959
drive:load(current)
6060
a2d.DialogOK()
61-
test.Snap("verify Calculator opened")
61+
test.ExpectEquals(a2dtest.GetFrontWindowTitle(), "Calc", "Calculator should be open")
6262
a2d.CloseWindow()
6363
end)
6464

@@ -72,6 +72,6 @@ test.Step(
7272
test.Snap("verify alert shown")
7373
drive:load(current)
7474
a2d.DialogOK()
75-
test.Snap("verify CONTROL.PANELS window opemed")
75+
test.ExpectEqualsIgnoreCase(a2dtest.GetFrontWindowTitle(), "CONTROL.PANELS", "Control Panels window should be open")
7676
a2d.CloseWindow()
7777
end)

tests/calculator.lua

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@
55
66
============================================================]]--
77

8-
local INITIAL_HEADER_X = 280
9-
local INITIAL_HEADER_Y = 55
10-
118
test.Step(
129
"Cursor doesn't home",
1310
function()
@@ -20,8 +17,10 @@ test.Step(
2017
"Move window and mouse cursor",
2118
function()
2219
a2d.OpenPath("/A2.DESKTOP/APPLE.MENU/CALCULATOR")
20+
local x,y = a2dtest.GetFrontWindowDragCoords()
21+
2322
a2d.InMouseKeysMode(function(m)
24-
m.MoveToApproximately(INITIAL_HEADER_X,INITIAL_HEADER_Y)
23+
m.MoveToApproximately(x,y)
2524
m.ButtonDown()
2625
m.MoveToApproximately(400,100)
2726
m.ButtonUp()
@@ -35,8 +34,10 @@ test.Step(
3534
"Window and volume icons",
3635
function()
3736
a2d.OpenPath("/A2.DESKTOP/APPLE.MENU/CALCULATOR")
37+
local x,y = a2dtest.GetFrontWindowDragCoords()
38+
3839
a2d.InMouseKeysMode(function(m)
39-
m.MoveToApproximately(INITIAL_HEADER_X,INITIAL_HEADER_Y)
40+
m.MoveToApproximately(x,y)
4041
m.ButtonDown()
4142
m.MoveToApproximately(500,20)
4243
m.ButtonUp()
@@ -58,8 +59,10 @@ test.Step(
5859
"Obscured window",
5960
function()
6061
a2d.OpenPath("/A2.DESKTOP/APPLE.MENU/CALCULATOR")
62+
local x,y = a2dtest.GetFrontWindowDragCoords()
63+
6164
a2d.InMouseKeysMode(function(m)
62-
m.MoveToApproximately(INITIAL_HEADER_X,INITIAL_HEADER_Y)
65+
m.MoveToApproximately(x,y)
6366
m.ButtonDown()
6467
m.MoveToApproximately(280,191)
6568
m.ButtonUp()

tests/close_all.lua

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,17 @@
88
test.Step(
99
"Close all using modifier-click",
1010
function()
11-
a2dtest.ExpectNothingHappened(function()
12-
a2d.ClearSelection()
13-
a2d.OpenPath("/A2.DESKTOP/EXTRAS", true) -- leave parent open
14-
a2d.InMouseKeysMode(function(m)
15-
m.MoveToApproximately(40, 26)
16-
apple2.PressOA()
17-
m.Click()
18-
apple2.ReleaseOA()
19-
a2d.WaitForRepaint()
20-
m.MoveToApproximately(0,0)
21-
end)
22-
a2d.ClearSelection()
11+
a2d.ClearSelection()
12+
a2d.OpenPath("/A2.DESKTOP/EXTRAS", true) -- leave parent open
13+
local x,y = a2dtest.GetFrontWindowCloseBoxCoords()
14+
a2d.InMouseKeysMode(function(m)
15+
m.MoveToApproximately(x,y)
16+
apple2.PressOA()
17+
m.Click()
18+
apple2.ReleaseOA()
2319
end)
20+
a2d.WaitForRepaint()
21+
test.ExpectEquals(a2dtest.GetWindowCount(), 0, "all windows should be closed")
2422
end)
2523

2624
test.Variants(
@@ -30,16 +28,14 @@ test.Variants(
3028
},
3129
function(idx)
3230
a2d.ClearSelection()
33-
a2dtest.ExpectNothingHappened(function()
34-
a2d.OpenPath("/A2.DESKTOP/EXTRAS", true) -- leave parent open
35-
if idx == 1 then
36-
a2d.OASAShortcut("W")
37-
else
38-
a2d.OASAShortcut("w")
39-
end
40-
a2d.WaitForRepaint()
41-
a2d.ClearSelection()
42-
end)
31+
a2d.OpenPath("/A2.DESKTOP/EXTRAS", true) -- leave parent open
32+
if idx == 1 then
33+
a2d.OASAShortcut("W")
34+
else
35+
a2d.OASAShortcut("w")
36+
end
37+
a2d.WaitForRepaint()
38+
test.ExpectEquals(a2dtest.GetWindowCount(), 0, "all windows should be closed")
4339
end)
4440

4541
--[[
@@ -64,7 +60,7 @@ test.Variants(
6460
else
6561
apple2.ReleaseOA()
6662
end
67-
test.Snap("verify all windows closed")
63+
test.ExpectEquals(a2dtest.GetWindowCount(), 0, "all windows should be closed")
6864
end)
6965
]]--
7066

@@ -85,6 +81,6 @@ end)
8581
a2d.OASAShortcut("w")
8682
end
8783
a2d.WaitForRepaint()
88-
test.Snap("verify all windows closed")
84+
test.ExpectEquals(a2dtest.GetWindowCount(), 0, "all windows should be closed")
8985
end)
9086
]]--

tests/close_window.lua

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@ test.Step(
1616
function()
1717
a2d.OpenPath("/A2.DESKTOP")
1818
a2d.SelectAndOpen("EXTRAS")
19+
local count = a2dtest.GetWindowCount()
20+
local x,y = a2dtest.GetFrontWindowCloseBoxCoords()
1921
a2d.InMouseKeysMode(function(m)
20-
m.MoveToApproximately(40, 26)
22+
m.MoveToApproximately(x,y)
2123
m.Click()
2224
end)
2325
a2d.WaitForRepaint()
24-
test.Snap("verify only one window closed")
26+
test.ExpectEquals(a2dtest.GetWindowCount(), count - 1, "one window should have closed")
2527
a2d.CloseAllWindows()
2628
end)
2729

@@ -35,6 +37,7 @@ test.Variants(
3537
function(idx)
3638
a2d.OpenPath("/A2.DESKTOP")
3739
a2d.SelectAndOpen("EXTRAS")
40+
local count = a2dtest.GetWindowCount()
3841
a2d.OpenMenu(a2d.FILE_MENU)
3942
if idx == 1 then
4043
a2d.OAShortcut("W")

tests/date_and_time.lua

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,16 @@ test.Step(
2323
"Escape and Return",
2424
function()
2525
a2d.SelectPath("/A2.DESKTOP/APPLE.MENU/CONTROL.PANELS/DATE.AND.TIME")
26-
27-
a2dtest.ExpectNothingHappened(function()
28-
a2d.OpenSelection()
29-
apple2.ReturnKey()
30-
a2d.WaitForRepaint()
31-
end)
32-
33-
a2dtest.ExpectNothingHappened(function()
34-
a2d.OpenSelection()
35-
apple2.EscapeKey()
36-
a2d.WaitForRepaint()
37-
end)
26+
local count = a2dtest.GetWindowCount()
27+
a2d.OpenSelection()
28+
apple2.ReturnKey()
29+
a2d.WaitForRepaint()
30+
test.ExpectEquals(a2dtest.GetWindowCount(), count, "expect window closed")
31+
32+
a2d.OpenSelection()
33+
apple2.EscapeKey()
34+
a2d.WaitForRepaint()
35+
test.ExpectEquals(a2dtest.GetWindowCount(), count, "expect window closed")
3836

3937
a2d.CloseAllWindows()
4038
end)

tests/desk_accessories.lua

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ test.Step(
88
a2d.CloseWindow()
99
end)
1010

11-
function MoveDoesntRepaintTest(name, path, x, y, opt_threshold)
11+
function MoveDoesntRepaintTest(name, path, opt_threshold)
1212
test.Step(
1313
name .. " doesn't repaint on non-move",
1414
function()
@@ -25,6 +25,9 @@ function MoveDoesntRepaintTest(name, path, x, y, opt_threshold)
2525

2626
a2d.SelectPath(path)
2727
a2d.OpenSelection()
28+
29+
local x,y = a2dtest.GetFrontWindowDragCoords()
30+
2831
a2d.InMouseKeysMode(function(m)
2932
m.MoveToApproximately(x,y)
3033
emu.wait(2/60)
@@ -45,21 +48,21 @@ function MoveDoesntRepaintTest(name, path, x, y, opt_threshold)
4548
end)
4649
end
4750

48-
MoveDoesntRepaintTest("Calculator", "/A2.DESKTOP/APPLE.MENU/CALCULATOR", 280, 55)
49-
MoveDoesntRepaintTest("Calendar", "/A2.DESKTOP/APPLE.MENU/CALENDAR", 280, 40)
50-
MoveDoesntRepaintTest("Key Caps", "/A2.DESKTOP/APPLE.MENU/KEY.CAPS", 280, 50)
51-
MoveDoesntRepaintTest("Control Panel", "/A2.DESKTOP/APPLE.MENU/CONTROL.PANELS/CONTROL.PANEL", 280, 30)
52-
MoveDoesntRepaintTest("Joystick", "/A2.DESKTOP/APPLE.MENU/CONTROL.PANELS/JOYSTICK", 280, 50, 0.02)
53-
MoveDoesntRepaintTest("Map", "/A2.DESKTOP/APPLE.MENU/CONTROL.PANELS/MAP", 280, 40)
54-
MoveDoesntRepaintTest("Options", "/A2.DESKTOP/APPLE.MENU/CONTROL.PANELS/OPTIONS", 280, 45)
55-
MoveDoesntRepaintTest("Views", "/A2.DESKTOP/APPLE.MENU/CONTROL.PANELS/VIEWS", 280, 50)
56-
MoveDoesntRepaintTest("Bounce", "/A2.DESKTOP/APPLE.MENU/TOYS/BOUNCE", 280, 45, 0.05)
57-
MoveDoesntRepaintTest("Eyes", "/A2.DESKTOP/APPLE.MENU/TOYS/EYES", 280, 60)
58-
MoveDoesntRepaintTest("Lights Out", "/A2.DESKTOP/APPLE.MENU/TOYS/LIGHTS.OUT", 280, 60)
59-
MoveDoesntRepaintTest("Neko", "/A2.DESKTOP/APPLE.MENU/TOYS/NEKO", 280, 50)
60-
MoveDoesntRepaintTest("Puzzle", "/A2.DESKTOP/APPLE.MENU/TOYS/PUZZLE", 280, 70)
61-
MoveDoesntRepaintTest("CD Remote", "/A2.DESKTOP/EXTRAS/CD.REMOTE", 280, 70)
62-
MoveDoesntRepaintTest("Scientific Calculator", "/A2.DESKTOP/EXTRAS/SCI.CALC", 280, 50)
51+
MoveDoesntRepaintTest("Calculator", "/A2.DESKTOP/APPLE.MENU/CALCULATOR")
52+
MoveDoesntRepaintTest("Calendar", "/A2.DESKTOP/APPLE.MENU/CALENDAR")
53+
MoveDoesntRepaintTest("Key Caps", "/A2.DESKTOP/APPLE.MENU/KEY.CAPS")
54+
MoveDoesntRepaintTest("Control Panel", "/A2.DESKTOP/APPLE.MENU/CONTROL.PANELS/CONTROL.PANEL")
55+
MoveDoesntRepaintTest("Joystick", "/A2.DESKTOP/APPLE.MENU/CONTROL.PANELS/JOYSTICK", 0.02)
56+
MoveDoesntRepaintTest("Map", "/A2.DESKTOP/APPLE.MENU/CONTROL.PANELS/MAP")
57+
MoveDoesntRepaintTest("Options", "/A2.DESKTOP/APPLE.MENU/CONTROL.PANELS/OPTIONS")
58+
MoveDoesntRepaintTest("Views", "/A2.DESKTOP/APPLE.MENU/CONTROL.PANELS/VIEWS")
59+
MoveDoesntRepaintTest("Bounce", "/A2.DESKTOP/APPLE.MENU/TOYS/BOUNCE", 0.05)
60+
MoveDoesntRepaintTest("Eyes", "/A2.DESKTOP/APPLE.MENU/TOYS/EYES")
61+
MoveDoesntRepaintTest("Lights Out", "/A2.DESKTOP/APPLE.MENU/TOYS/LIGHTS.OUT")
62+
MoveDoesntRepaintTest("Neko", "/A2.DESKTOP/APPLE.MENU/TOYS/NEKO")
63+
MoveDoesntRepaintTest("Puzzle", "/A2.DESKTOP/APPLE.MENU/TOYS/PUZZLE")
64+
MoveDoesntRepaintTest("CD Remote", "/A2.DESKTOP/EXTRAS/CD.REMOTE")
65+
MoveDoesntRepaintTest("Scientific Calculator", "/A2.DESKTOP/EXTRAS/SCI.CALC")
6366

6467
-- ============================================================
6568

0 commit comments

Comments
 (0)