go-scopes/common/testing/testing.go

144 lines
2.8 KiB
Go

// Package testing provides a testing object T
// with functions for classical unit testing.
package testing
import (
"bufio"
"fmt"
"os"
"regexp"
"testing"
"time"
lib "git.sr.ht/~cco/go-scopes"
"git.sr.ht/~cco/go-scopes/app"
"git.sr.ht/~cco/go-scopes/core/context"
"git.sr.ht/~cco/go-scopes/core/message"
"git.sr.ht/~cco/go-scopes/logging"
)
func Start(ctx lib.Context) {
app.Start(ctx)
}
// definitions
type Map map[string]interface{}
type T struct {
Base *testing.T
Ctx lib.Context
}
func MakeT(tbase *testing.T) *T {
return &T{
Base: tbase,
}
}
func SetUp(tbase *testing.T) *T {
t := MakeT(tbase)
logging.SetDefault()
return t
}
func SetUpApp(tbase *testing.T, cfg lib.Config) *T {
appCfg := cfg.(*app.Cfg)
t := SetUp(tbase)
t.Ctx = context.AppContext(cfg).WithState(t)
logging.Setup(t.Ctx, appCfg.Logging, appCfg.Home)
cfg.Starter()(t.Ctx)
time.Sleep(100 * time.Millisecond)
return t
}
func (t *T) TearDownApp() {
// give actors time to recieve all messages:
time.Sleep(100 * time.Millisecond)
//t.Check()
lib.Send(t.Ctx, message.SimpleAddress("testing"), message.Quit)
t.Ctx.WaitGroup().Wait()
//t.AssertNoUncheckedMessages()
}
func (t *T) LogCheck(pr bool) int {
count := 0
f, _ := os.Open("log/scopes.log")
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
count++
if pr {
txt := scanner.Text()
data := logging.Parse(txt)
level := data["level"]
message := data["message"]
delete(data, "level")
delete(data, "message")
delete(data, "time")
srv := "-"
if data["service"] != nil {
srv = data["service"].(string)
delete(data, "service")
}
dstr := ""
if len(data) > 0 {
dstr = fmt.Sprintf("; %+v", data)
}
fmt.Printf("%d: %s: %s - %s%s\n", count, level, srv, message, dstr)
//fmt.Println(scanner.Text())
}
}
return count
}
func GetT(ctx lib.Context) *T {
return ctx.Parent().State().(*T)
}
// testing methods
func (t *T) Run(name string, f func(*T)) bool {
return t.Base.Run(name, func(_ *testing.T) {
f(t)
})
}
func (t *T) LogErr(txt string, fields Map) {
t.Base.Helper()
t.Base.Errorf("%v, %+v", txt, fields)
}
func (t *T) AssertEqual(have interface{}, want interface{}) {
t.Base.Helper()
if have != want {
t.LogErr("AssertEqual", Map{"have": have, "want": want})
}
}
func (t *T) AssertMatch(have string, want string) {
t.Base.Helper()
match, _ := regexp.MatchString(Normalize(want), Normalize(have))
if !match {
t.LogErr("AssertMatch", Map{"have": have, "want": want})
}
}
// testing functions: generic functions may not be methods
func AssertOneOf[V comparable](t *T, have V, want []V) {
t.Base.Helper()
for _, w := range want {
if have == w {
return
}
}
t.LogErr("AssertOneOf", Map{"have": have, "want": want})
}
// helpers
func Normalize(s string) string {
re, _ := regexp.Compile(`\s*`)
return re.ReplaceAllString(s, "")
}