From 55e515554f2df32390c75a6e6f84692eb2550016 Mon Sep 17 00:00:00 2001 From: Zellyn Hunter Date: Wed, 30 Nov 2016 22:29:42 -0500 Subject: [PATCH] supermon: add first simple test for writing a file 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. --- lib/supermon/supermon.go | 40 ++++++++++++++++------- lib/supermon/supermon_test.go | 61 +++++++++++++++++++++++++++++------ 2 files changed, 80 insertions(+), 21 deletions(-) diff --git a/lib/supermon/supermon.go b/lib/supermon/supermon.go index 98347e2..64c9246 100644 --- a/lib/supermon/supermon.go +++ b/lib/supermon/supermon.go @@ -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 { @@ -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 { @@ -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 } @@ -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) } @@ -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{} @@ -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, @@ -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, @@ -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") @@ -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 } @@ -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 diff --git a/lib/supermon/supermon_test.go b/lib/supermon/supermon_test.go index 1d1007d..a4c0a97 100644 --- a/lib/supermon/supermon_test.go +++ b/lib/supermon/supermon_test.go @@ -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) { @@ -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) } @@ -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) + } +}