Skip to content

Commit

Permalink
supermon: add first simple test for writing a file
Browse files Browse the repository at this point in the history
Also removes op.symbols, since the map was computed at operator
construction time, and never updated to match the actual symbol table
as it changed.
  • Loading branch information
zellyn committed Dec 1, 2016
1 parent b9a8384 commit 55e5155
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 21 deletions.
40 changes: 28 additions & 12 deletions lib/supermon/supermon.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,10 @@ type Symbol struct {
Link int
}

func (s Symbol) String() string {
return fmt.Sprintf("{%s:%04X:%d}", s.Name, s.Address, s.Link)
}

// decodeSymbol decodes a Super-Mon encoded symbol table entry,
// returning the string representation.
func decodeSymbol(five []byte, extra byte) string {
Expand Down Expand Up @@ -420,6 +424,17 @@ func (st SymbolTable) SymbolsByAddress() map[uint16][]Symbol {
return result
}

// SymbolsForAddress returns a slice of symbols for a given address.
func (st SymbolTable) SymbolsForAddress(address uint16) []Symbol {
result := []Symbol{}
for _, symbol := range st {
if symbol.Address == address {
result = append(result, symbol)
}
}
return result
}

// DeleteSymbol deletes an existing symbol. Returns true if the named
// symbol was found.
func (st SymbolTable) DeleteSymbol(name string) bool {
Expand Down Expand Up @@ -483,7 +498,8 @@ func (st SymbolTable) AddSymbol(name string, address uint16) error {

// NameForFile returns a string representation of a filename:
// either DFxx, or a symbol, if one exists for that value.
func NameForFile(file byte, symbols []Symbol) string {
func NameForFile(file byte, st SymbolTable) string {
symbols := st.SymbolsForAddress(0xDF00 + uint16(file))
if len(symbols) > 0 {
return symbols[0].Name
}
Expand All @@ -492,7 +508,8 @@ func NameForFile(file byte, symbols []Symbol) string {

// FullnameForFile returns a string representation of a filename:
// either DFxx, or a DFxx:symbol, if one exists for that value.
func FullnameForFile(file byte, symbols []Symbol) string {
func FullnameForFile(file byte, st SymbolTable) string {
symbols := st.SymbolsForAddress(0xDF00 + uint16(file))
if len(symbols) > 0 {
return fmt.Sprintf("DF%02X:%s", file, symbols[0].Name)
}
Expand Down Expand Up @@ -570,10 +587,9 @@ func (st SymbolTable) FilesForCompoundName(filename string) (numFile byte, named
// operator is a disk.Operator - an interface for performing
// high-level operations on files and directories.
type operator struct {
sd disk.SectorDisk
sm SectorMap
st SymbolTable
symbols map[uint16][]Symbol
sd disk.SectorDisk
sm SectorMap
st SymbolTable
}

var _ disk.Operator = operator{}
Expand Down Expand Up @@ -603,10 +619,9 @@ func (o operator) Catalog(subdir string) ([]disk.Descriptor, error) {
if l == 0 {
continue
}
fileAddr := 0xDF00 + uint16(file)
descs = append(descs, disk.Descriptor{
Name: NameForFile(file, o.symbols[fileAddr]),
Fullname: FullnameForFile(file, o.symbols[fileAddr]),
Name: NameForFile(file, o.st),
Fullname: FullnameForFile(file, o.st),
Sectors: l,
Length: l * 256,
Locked: false,
Expand All @@ -630,7 +645,7 @@ func (o operator) GetFile(filename string) (disk.FileInfo, error) {
return disk.FileInfo{}, fmt.Errorf("file DF%02x not fount", file)
}
desc := disk.Descriptor{
Name: NameForFile(file, o.symbols[0xDF00+uint16(file)]),
Name: NameForFile(file, o.st),
Sectors: len(data) / 256,
Length: len(data),
Locked: false,
Expand Down Expand Up @@ -684,6 +699,7 @@ func (o operator) PutFile(fileInfo disk.FileInfo, overwrite bool) (existed bool,
if err != nil {
return false, err
}
fmt.Printf("PLUGH: numFile: %v, namedFile: %v, symbol: %v\n", numFile, namedFile, symbol)
if symbol != "" {
if o.st == nil {
return false, fmt.Errorf("cannot use symbolic names on disks without valid symbol tables in files 0x03 and 0x04")
Expand All @@ -703,9 +719,10 @@ func (o operator) PutFile(fileInfo disk.FileInfo, overwrite bool) (existed bool,
return existed, err
}
if namedFile != numFile && symbol != "" {
if err := o.st.AddSymbol(symbol, 0xDF+uint16(numFile)); err != nil {
if err := o.st.AddSymbol(symbol, 0xDF00+uint16(numFile)); err != nil {
return existed, err
}
fmt.Println("PLUGH: about to write symbol table: %v", o.st)
if err := o.sm.WriteSymbolTable(o.sd, o.st); err != nil {
return existed, err
}
Expand All @@ -729,7 +746,6 @@ func operatorFactory(sd disk.SectorDisk) (disk.Operator, error) {
st, err := sm.ReadSymbolTable(sd)
if err == nil {
op.st = st
op.symbols = st.SymbolsByAddress()
}

return op, nil
Expand Down
61 changes: 52 additions & 9 deletions lib/supermon/supermon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ import (

const testDisk = "testdata/chacha20.dsk"

const cities = `It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way - in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.`

// The extra newline pads us to 256 bytes…
const hamlet = `To be, or not to be, that is the question:
Whether 'tis Nobler in the mind to suffer
The Slings and Arrows of outrageous Fortune,
Or to take Arms against a Sea of troubles,
And by opposing end them: to die, to sleep
No more; and by a sleep, to say we end
`

// loadSectorMap loads a sector map for the disk image contained in
// filename. It returns the sector map and a sector disk.
func loadSectorMap(filename string) (SectorMap, disk.SectorDisk, error) {
Expand Down Expand Up @@ -127,15 +139,7 @@ func TestGetFile(t *testing.T) {
t.Fatal(err)
}
got := string(file.Data)
// The extra newline pads us to 256 bytes…
want := `To be, or not to be, that is the question:
Whether 'tis Nobler in the mind to suffer
The Slings and Arrows of outrageous Fortune,
Or to take Arms against a Sea of troubles,
And by opposing end them: to die, to sleep
No more; and by a sleep, to say we end
`
want := hamlet
if got != want {
t.Errorf("Incorrect result for GetFile(\"TOBE\"): want %q; got %q", want, got)
}
Expand Down Expand Up @@ -205,3 +209,42 @@ func TestReadWriteSymbolTable(t *testing.T) {
t.Fatal("Saved and reloaded symbol table differs from original symbol table")
}
}

// TestPutFile tests the creation of a file, using the Operator
// interface.
func TestPutFile(t *testing.T) {
sd, err := disk.Open(testDisk)
if err != nil {
t.Fatal(err)
}
op, err := disk.OperatorFor(sd)
if err != nil {
t.Fatal(err)
}
contents := []byte(cities)
fileInfo := disk.FileInfo{
Descriptor: disk.Descriptor{
Name: "FNEWFILE",
Length: len(contents),
Type: disk.FiletypeBinary,
},
Data: contents,
}
existed, err := op.PutFile(fileInfo, false)
if err != nil {
t.Fatal(err)
}
if existed {
t.Errorf("want existed=%v; got %v", false, existed)
}

fds, err := op.Catalog("")
if err != nil {
t.Fatal(err)
}
last := fds[len(fds)-1]
want := "DF0B:FNEWFILE"
if got := last.Fullname; got != want {
t.Fatalf("Want last file on disk's FullName=%q; got %q", want, got)
}
}

0 comments on commit 55e5155

Please sign in to comment.