c65gm/internal/optimizer/config_test.go

180 lines
4.3 KiB
Go

package optimizer
import (
"testing"
"c65gm/internal/preproc"
)
func TestNewConfigWithAll(t *testing.T) {
ps := preproc.NewPragmaSet(map[string]string{
"_P_OPT_ALL": "1",
"_P_OPT_DEBUG": "1",
})
cfg := NewConfig(ps)
if !cfg.Any() {
t.Error("expected Any()=true")
}
if !cfg.EnableLoad {
t.Error("expected EnableLoad=true from _P_OPT_ALL")
}
if !cfg.EnableImm {
t.Error("expected EnableImm=true from _P_OPT_ALL")
}
if !cfg.Debug {
t.Error("expected Debug=true")
}
}
func TestParseExcludeRange(t *testing.T) {
tests := []struct {
name string
input string
wantOk bool
wantS uint16
wantE uint16
}{
{"hex", "0xD000:0xDFFF", true, 0xD000, 0xDFFF},
{"hex lowercase", "0xd000:0xdfff", true, 0xD000, 0xDFFF},
{"hex mixed case", "0XD000:0XdFfF", true, 0xD000, 0xDFFF},
{"decimal", "53248:57343", true, 53248, 57343},
{"single address", "0xD020:0xD020", true, 0xD020, 0xD020},
{"invalid range", "0xFFFF:0x0000", false, 0, 0},
{"bad format", "garbage", false, 0, 0},
{"bad hex", "0xGGGG:0x0000", false, 0, 0},
{"too many colons", "0xD000:0xDFFF:extra", false, 0, 0},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r, err := ParseExcludeRange(tt.input)
if tt.wantOk {
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if r.Start != tt.wantS || r.End != tt.wantE {
t.Errorf("got %04X:%04X, want %04X:%04X", r.Start, r.End, tt.wantS, tt.wantE)
}
} else {
if err == nil {
t.Errorf("expected error, got %04X:%04X", r.Start, r.End)
}
}
})
}
}
func TestAddIORegions(t *testing.T) {
cfg := &Config{}
cfg.AddIORegions([]IORegion{
{Start: 0xD000, End: 0xDFFF},
})
if !cfg.IOMap[0xD000] {
t.Error("expected 0xD000 to be marked I/O")
}
if !cfg.IOMap[0xDFFF] {
t.Error("expected 0xDFFF to be marked I/O")
}
if cfg.IOMap[0xCFFF] {
t.Error("expected 0xCFFF to NOT be marked I/O")
}
if cfg.IOMap[0xE000] {
t.Error("expected 0xE000 to NOT be marked I/O")
}
}
func TestAddIORegionsMultiple(t *testing.T) {
cfg := &Config{}
cfg.AddIORegions([]IORegion{
{Start: 0xD000, End: 0xDFFF},
{Start: 0xDC00, End: 0xDC0F}, // overlaps — still correct
})
if !cfg.IOMap[0xD000] {
t.Error("expected 0xD000 I/O")
}
if !cfg.IOMap[0xDC00] {
t.Error("expected 0xDC00 I/O")
}
if !cfg.IOMap[0xDC0F] {
t.Error("expected 0xDC0F I/O")
}
}
func TestBuildIOMap(t *testing.T) {
p := preproc.NewPragma()
p.AddPragma("_P_OPT_IO", "$D000 $DFFF")
// Last pragma set should have _P_OPT_IO
ps := p.GetPragmaSetByIndex(p.GetCurrentPragmaSetIndex())
cfg := NewConfig(ps)
cfg.BuildIOMap(p)
if !cfg.IOMap[0xD000] {
t.Error("expected $D000 I/O from pragma")
}
if !cfg.IOMap[0xDFFF] {
t.Error("expected $DFFF I/O from pragma")
}
}
func TestBuildIOMapMultiple(t *testing.T) {
// Simulate two _P_OPT_IO pragmas
p := preproc.NewPragma()
p.AddPragma("_P_OPT_IO", "$D000 $DFFF")
p.AddPragma("_P_OPT_IO", "$DC00 $DC0F")
p.AddPragma("_P_SOMETHING_ELSE", "1")
// BuildIOMap scans ALL sets, finding _P_OPT_IO at index 1 and 2
ps := p.GetPragmaSetByIndex(p.GetCurrentPragmaSetIndex())
cfg := NewConfig(ps)
cfg.BuildIOMap(p)
if !cfg.IOMap[0xD000] {
t.Error("expected $D000 I/O")
}
if !cfg.IOMap[0xDC00] {
t.Error("expected $DC00 I/O")
}
}
func TestBuildIOMapEmpty(t *testing.T) {
p := preproc.NewPragma()
ps := p.GetPragmaSetByIndex(p.GetCurrentPragmaSetIndex())
cfg := NewConfig(ps)
cfg.BuildIOMap(p)
for _, addr := range []uint16{0, 0xD000, 0xFFFF} {
if cfg.IOMap[addr] {
t.Errorf("address %04X should not be I/O", addr)
}
}
}
func TestNewConfigPragmasAccumulate(t *testing.T) {
// Pragma sets COPY previous values — so last set has ALL pragmas
p := preproc.NewPragma()
p.AddPragma("_P_OPT_ALL", "1")
p.AddPragma("_P_OPT_DEBUG", "1")
p.AddPragma("_P_SOMETHING_ELSE", "1")
// Last set should have all three
ps := p.GetPragmaSetByIndex(p.GetCurrentPragmaSetIndex())
if v := ps.GetPragma("_P_OPT_ALL"); v != "1" {
t.Errorf("expected _P_OPT_ALL=1, got %q", v)
}
if v := ps.GetPragma("_P_OPT_DEBUG"); v != "1" {
t.Errorf("expected _P_OPT_DEBUG=1, got %q", v)
}
if v := ps.GetPragma("_P_SOMETHING_ELSE"); v != "1" {
t.Errorf("expected _P_SOMETHING_ELSE=1, got %q", v)
}
cfg := NewConfig(ps)
if !cfg.Any() {
t.Error("expected Any()=true")
}
if !cfg.Debug {
t.Error("expected Debug=true")
}
}