mirror of
https://github.com/taigrr/gopher-os
synced 2026-03-24 09:52:25 -07:00
acpi: test the parser against actual AML dumps
All dumps are located in the tabletest package. The DSDT/SSDT dumps were obtained by running an aml dump tool inside a virtualbox instance. The dumps were disassembled using the iasl tool (version 20180105) from Intel's reference ACPICA implementation. The parser-testsuite dumps were written by hand to ensure that all possible happy-paths in the parser were followed and then compiled into AML using the same iasl tool. The added TestParser function attempts to parse various sets of AML dumps and then uses the object tree pretty-printer to obtain a dump of the tree. The dump is then compared to an expected value (.exp files are also placed in the tabletest package). The test code supports passing the "-aml-regenerate-parser-exp-files" flag to update the exp files: go test -run TestParser -aml-regenerate-parser-exp-files
This commit is contained in:
@@ -2,14 +2,94 @@ package aml
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"gopheros/device/acpi/table"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
regenExpFiles = flag.Bool("aml-regenerate-parser-exp-files", false, "Regenerate the expected output files for AML parser tests against real AML files")
|
||||
)
|
||||
|
||||
func TestParser(t *testing.T) {
|
||||
flag.Parse()
|
||||
|
||||
pathToDumps := pkgDir() + "/../table/tabletest/"
|
||||
|
||||
specs := []struct {
|
||||
expTreeContentFile string
|
||||
tableFiles []string
|
||||
}{
|
||||
{
|
||||
"DSDT-SSDT.exp",
|
||||
[]string{"DSDT.aml", "SSDT.aml"},
|
||||
},
|
||||
{
|
||||
"parser-testsuite-DSDT.exp",
|
||||
[]string{"parser-testsuite-DSDT.aml"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, spec := range specs {
|
||||
t.Run(fmt.Sprintf("parse [%s]", strings.Join(spec.tableFiles, ", ")), func(t *testing.T) {
|
||||
var resolver = mockResolver{
|
||||
pathToDumps: pathToDumps,
|
||||
tableFiles: spec.tableFiles,
|
||||
}
|
||||
|
||||
tree := NewObjectTree()
|
||||
tree.CreateDefaultScopes(42)
|
||||
|
||||
p := NewParser(&testWriter{t: t}, tree)
|
||||
for tableIndex, tableFile := range spec.tableFiles {
|
||||
tableName := strings.Replace(tableFile, ".aml", "", -1)
|
||||
if err := p.ParseAML(uint8(tableIndex), tableName, resolver.LookupTable(tableName)); err != nil {
|
||||
t.Errorf("[%s]: %v", tableName, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Pretty-print tree
|
||||
var treeDump bytes.Buffer
|
||||
tree.PrettyPrint(&treeDump)
|
||||
|
||||
// Check if we need to rebuild the exp files
|
||||
pathToExpFile := filepath.Join(pathToDumps, spec.expTreeContentFile)
|
||||
if *regenExpFiles {
|
||||
f, err := os.Create(pathToExpFile)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() { _ = f.Close() }()
|
||||
|
||||
if _, err = treeDump.WriteTo(f); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("regenerated exp file contents: %s", pathToExpFile)
|
||||
return
|
||||
}
|
||||
|
||||
// Read the exp file and compare its contents to the generated dump
|
||||
expDump, err := ioutil.ReadFile(pathToExpFile)
|
||||
if err != nil {
|
||||
t.Fatalf("error opening exp file: %s; try running tests with -aml-regenerate-parser-exp-files", pathToExpFile)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(expDump, treeDump.Bytes()) {
|
||||
t.Fatal("parsed tree content does not match expected content")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseAMLErrors(t *testing.T) {
|
||||
t.Run("parseObjectList failed", func(t *testing.T) {
|
||||
p, resolver := parserForMockPayload(t, []byte{uint8(pOpBuffer)})
|
||||
@@ -903,3 +983,30 @@ func (m mockByteDataResolver) LookupTable(string) *table.SDTHeader {
|
||||
|
||||
return header
|
||||
}
|
||||
|
||||
func pkgDir() string {
|
||||
_, f, _, _ := runtime.Caller(1)
|
||||
return filepath.Dir(f)
|
||||
}
|
||||
|
||||
type mockResolver struct {
|
||||
pathToDumps string
|
||||
tableFiles []string
|
||||
}
|
||||
|
||||
func (m mockResolver) LookupTable(name string) *table.SDTHeader {
|
||||
for _, f := range m.tableFiles {
|
||||
if !strings.Contains(f, name) {
|
||||
continue
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadFile(filepath.Join(m.pathToDumps, f))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return (*table.SDTHeader)(unsafe.Pointer(&data[0]))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user