200 lines
4.8 KiB
Go
200 lines
4.8 KiB
Go
package analyzer
|
|
|
|
import "testing"
|
|
import "strings"
|
|
import "github.com/google/uuid"
|
|
import "git.tebibyte.media/fspl/fspl/lexer"
|
|
import "git.tebibyte.media/fspl/fspl/errors"
|
|
import "git.tebibyte.media/fspl/fspl/entity"
|
|
import "git.tebibyte.media/fspl/fspl/parser/fspl"
|
|
|
|
func testStringErr (
|
|
test *testing.T,
|
|
errMessage string,
|
|
errRow int,
|
|
errStart int,
|
|
input string,
|
|
) {
|
|
address := entity.Address("stream0.fspl")
|
|
ast, ok := treeOf(test, address, input, false)
|
|
if !ok { return }
|
|
|
|
tree := Tree { }
|
|
err := tree.Analyze(address.UUID(), nil, ast)
|
|
if err == nil {
|
|
test.Error("analyzer did not return error")
|
|
return
|
|
}
|
|
compareErr(test, address, string(address), errMessage, errRow, errStart, err)
|
|
}
|
|
|
|
func testString (test *testing.T, input string) {
|
|
address := entity.Address("stream0.fspl")
|
|
ast, ok := treeOf(test, address, input, false)
|
|
if !ok { return }
|
|
|
|
tree := Tree { }
|
|
err := tree.Analyze(address.UUID(), nil, ast)
|
|
if err != nil {
|
|
test.Error("analyzer returned error:\n" + errors.Format(err))
|
|
return
|
|
}
|
|
}
|
|
|
|
func testUnits (
|
|
test *testing.T,
|
|
main string,
|
|
dependencies ...string,
|
|
) {
|
|
if len(dependencies) % 2 != 0 {
|
|
panic("dependencies len must be even. forget an address?")
|
|
}
|
|
tree := Tree { }
|
|
nicknames := make(map[string] uuid.UUID)
|
|
|
|
// dependencies
|
|
for index := 0; index < len(dependencies) - 1; index += 2 {
|
|
address := entity.Address(dependencies[index])
|
|
source := dependencies[index + 1]
|
|
ast, ok := treeOf(test, address, source, true)
|
|
if !ok { return }
|
|
|
|
err := tree.Analyze(address.UUID(), nicknames, ast)
|
|
if err != nil {
|
|
test.Error("analyzer returned error:\n" + errors.Format(err))
|
|
return
|
|
}
|
|
|
|
unit := address.UUID()
|
|
nickname, ok := address.Nickname()
|
|
if !ok {
|
|
test.Errorf("could not generate nickname for %v", address)
|
|
return
|
|
}
|
|
nicknames[nickname] = unit
|
|
}
|
|
|
|
// main
|
|
address := entity.Address("main.fspl")
|
|
ast, ok := treeOf(test, address, main, false)
|
|
if !ok { return }
|
|
err := tree.Analyze(address.UUID(), nicknames, ast)
|
|
if err != nil {
|
|
test.Error("analyzer returned error:\n" + errors.Format(err))
|
|
return
|
|
}
|
|
}
|
|
|
|
func testUnitsErr (
|
|
test *testing.T,
|
|
errFile string,
|
|
errMessage string,
|
|
errRow int,
|
|
errStart int,
|
|
|
|
main string,
|
|
dependencies ...string,
|
|
) {
|
|
if len(dependencies) % 2 != 0 {
|
|
panic("dependencies len must be even. forget an address?")
|
|
}
|
|
tree := Tree { }
|
|
nicknames := make(map[string] uuid.UUID)
|
|
|
|
// dependencies
|
|
for index := 0; index < len(dependencies) - 1; index += 2 {
|
|
address := entity.Address(dependencies[index])
|
|
source := dependencies[index + 1]
|
|
ast, ok := treeOf(test, address, source, true)
|
|
if !ok { return }
|
|
|
|
err := tree.Analyze(address.UUID(), nicknames, ast)
|
|
if err != nil {
|
|
compareErr(test, address, errFile, errMessage, errRow, errStart, err)
|
|
return
|
|
}
|
|
|
|
unit := address.UUID()
|
|
nickname, ok := address.Nickname()
|
|
if !ok {
|
|
test.Errorf("could not generate nickname for %v", address)
|
|
return
|
|
}
|
|
nicknames[nickname] = unit
|
|
}
|
|
|
|
// main
|
|
address := entity.Address("main.fspl")
|
|
ast, ok := treeOf(test, address, main, false)
|
|
if !ok { return }
|
|
err := tree.Analyze(address.UUID(), nicknames, ast)
|
|
if err != nil {
|
|
compareErr(test, address, errFile, errMessage, errRow, errStart, err)
|
|
return
|
|
}
|
|
|
|
test.Error("analyzer did not return error")
|
|
}
|
|
|
|
func treeOf (test *testing.T, address entity.Address, input string, skim bool) (fsplParser.Tree, bool) {
|
|
ast := fsplParser.Tree { }
|
|
lx, err := lexer.LexReader (
|
|
string(address),
|
|
strings.NewReader(input))
|
|
if err != nil {
|
|
test.Error("lexer returned error:\n" + errors.Format(err))
|
|
return ast, false
|
|
}
|
|
if skim {
|
|
err = ast.Skim(lx)
|
|
} else {
|
|
err = ast.Parse(lx)
|
|
}
|
|
if err != nil {
|
|
test.Error("parser returned error:\n" + errors.Format(err))
|
|
return ast, false
|
|
}
|
|
|
|
return ast, true
|
|
}
|
|
|
|
func compareErr (
|
|
test *testing.T,
|
|
address entity.Address,
|
|
errFile string,
|
|
errMessage string,
|
|
errRow int,
|
|
errStart int,
|
|
err error,
|
|
) bool {
|
|
got := err.(errors.Error)
|
|
gotMessage := got.Error()
|
|
gotFile := got.Position().File
|
|
gotRow := got.Position().Row + 1
|
|
gotStart := got.Position().Start + 1
|
|
|
|
correct :=
|
|
gotFile == errFile &&
|
|
gotMessage == errMessage &&
|
|
gotRow == errRow &&
|
|
gotStart == errStart
|
|
if correct { return true }
|
|
|
|
test.Log("errors do not match:")
|
|
if gotMessage != errMessage {
|
|
test.Log("- messages do not match:")
|
|
test.Logf(" [%s]", gotMessage)
|
|
test.Logf(" [%s]", errMessage)
|
|
}
|
|
if gotRow != errRow {
|
|
test.Logf("- rows do not match: (%d, %d)", gotRow, errRow)
|
|
}
|
|
if gotStart != errStart {
|
|
test.Logf("- columns do not match: (%d, %d)", gotStart, errStart)
|
|
}
|
|
test.Log("got:\n" + errors.Format(got))
|
|
test.Logf("correct:\n%v:%v: %v", errRow, errStart, errMessage)
|
|
test.Fail()
|
|
return false
|
|
}
|