mirror of
https://github.com/JetSetIlly/Gopher2600.git
synced 2025-04-02 11:02:17 -04:00
added -fpscap to emulate() function (used by both playmode and the debugger) making it a good alternative to the -display option getting performance mode to work with an increasingly complex gui-emulation communication just isn't worth it. it would make the code too complex. this paves the way for removing the Emulation interface and using a straight-forward Emulation type, which will be current Debugger type renamd. the Debugger type is currently handling the playmode, performing well and allowing tighter integration of the debugger and playmode.
186 lines
4.1 KiB
Go
186 lines
4.1 KiB
Go
// This file is part of Gopher2600.
|
|
//
|
|
// Gopher2600 is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Gopher2600 is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
package debugger_test
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/jetsetilly/gopher2600/cartridgeloader"
|
|
"github.com/jetsetilly/gopher2600/debugger"
|
|
"github.com/jetsetilly/gopher2600/debugger/terminal"
|
|
"github.com/jetsetilly/gopher2600/emulation"
|
|
"github.com/jetsetilly/gopher2600/gui"
|
|
"github.com/jetsetilly/gopher2600/prefs"
|
|
)
|
|
|
|
type mockGUI struct{}
|
|
|
|
func (g *mockGUI) SetFeature(request gui.FeatureReq, args ...gui.FeatureReqData) error {
|
|
return nil
|
|
}
|
|
|
|
type mockTerm struct {
|
|
t *testing.T
|
|
inp chan string
|
|
out chan string
|
|
output []string
|
|
}
|
|
|
|
func newMockTerm(t *testing.T) *mockTerm {
|
|
trm := &mockTerm{
|
|
t: t,
|
|
inp: make(chan string),
|
|
out: make(chan string, 100),
|
|
}
|
|
return trm
|
|
}
|
|
|
|
func (trm *mockTerm) Initialise() error {
|
|
return nil
|
|
}
|
|
|
|
func (trm *mockTerm) CleanUp() {
|
|
}
|
|
|
|
func (trm *mockTerm) RegisterTabCompletion(_ terminal.TabCompletion) {
|
|
}
|
|
|
|
func (trm *mockTerm) Silence(silenced bool) {
|
|
}
|
|
|
|
func (trm *mockTerm) TermRead(buffer []byte, _ terminal.Prompt, _ *terminal.ReadEvents) (int, error) {
|
|
s := <-trm.inp
|
|
copy(buffer, s)
|
|
return len(s) + 1, nil
|
|
}
|
|
|
|
func (trm *mockTerm) TermReadCheck() bool {
|
|
return false
|
|
}
|
|
|
|
func (trm *mockTerm) IsInteractive() bool {
|
|
return false
|
|
}
|
|
|
|
func (trm *mockTerm) IsRealTerminal() bool {
|
|
return false
|
|
}
|
|
|
|
func (trm *mockTerm) TermPrintLine(sty terminal.Style, s string) {
|
|
if sty == terminal.StyleEcho {
|
|
return
|
|
}
|
|
|
|
trm.out <- s
|
|
}
|
|
|
|
func (trm *mockTerm) sndInput(s string) {
|
|
trm.output = make([]string, 0, 10)
|
|
trm.inp <- s
|
|
}
|
|
|
|
func (trm *mockTerm) rcvOutput() {
|
|
empty := false
|
|
for !empty {
|
|
select {
|
|
case s := <-trm.out:
|
|
trm.output = append(trm.output, s)
|
|
|
|
// the amount of output sent by the debugger is unpredictable so a
|
|
// timeout is necessary. a matter of milliseconds should be sufficient
|
|
case <-time.After(10 * time.Millisecond):
|
|
empty = true
|
|
}
|
|
}
|
|
}
|
|
|
|
// cmpOutput compares the string argument with the *last line* of the most
|
|
// recent output. it can easily be adapted to compare the whole output if
|
|
// necessary.
|
|
func (trm *mockTerm) cmpOutput(s string) {
|
|
trm.rcvOutput()
|
|
|
|
if len(trm.output) == 0 {
|
|
if len(s) != 0 {
|
|
trm.t.Errorf(fmt.Sprintf("unexpected debugger output (nothing) should be (%s)", s))
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
l := len(trm.output) - 1
|
|
|
|
if trm.output[l] == s {
|
|
return
|
|
}
|
|
|
|
trm.t.Errorf(fmt.Sprintf("unexpected debugger output (%s) should be (%s)", trm.output[l], s))
|
|
}
|
|
|
|
func (trm *mockTerm) testSequence() {
|
|
defer func() { trm.sndInput("QUIT") }()
|
|
trm.testBreakpoints()
|
|
trm.testTraps()
|
|
trm.testWatches()
|
|
}
|
|
|
|
func TestDebugger_withNonExistantInitScript(t *testing.T) {
|
|
prefs.DisableSaving = true
|
|
|
|
var trm *mockTerm
|
|
|
|
create := func(e emulation.Emulation) (gui.GUI, terminal.Terminal, error) {
|
|
trm = newMockTerm(t)
|
|
return &mockGUI{}, trm, nil
|
|
}
|
|
|
|
dbg, err := debugger.NewDebugger(create, "AUTO", false, true)
|
|
if err != nil {
|
|
t.Fatalf(err.Error())
|
|
}
|
|
|
|
go trm.testSequence()
|
|
|
|
err = dbg.Start(emulation.ModeDebugger, "non_existent_script", cartridgeloader.Loader{})
|
|
if err != nil {
|
|
t.Fatalf(err.Error())
|
|
}
|
|
}
|
|
|
|
func TestDebugger(t *testing.T) {
|
|
prefs.DisableSaving = true
|
|
|
|
var trm *mockTerm
|
|
|
|
create := func(e emulation.Emulation) (gui.GUI, terminal.Terminal, error) {
|
|
trm = newMockTerm(t)
|
|
return &mockGUI{}, trm, nil
|
|
}
|
|
|
|
dbg, err := debugger.NewDebugger(create, "AUTO", false, true)
|
|
if err != nil {
|
|
t.Fatalf(err.Error())
|
|
}
|
|
|
|
go trm.testSequence()
|
|
|
|
err = dbg.Start(emulation.ModeDebugger, "", cartridgeloader.Loader{})
|
|
if err != nil {
|
|
t.Fatalf(err.Error())
|
|
}
|
|
}
|