mirror of
https://github.com/luxfi/consensus.git
synced 2026-09-24 00:26:58 +00:00
341 lines
7.1 KiB
Go
341 lines
7.1 KiB
Go
// +build ignore
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"go/ast"
|
|
"go/parser"
|
|
"go/token"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"text/template"
|
|
)
|
|
|
|
const testTemplate = `package {{.Package}}
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
{{range .Imports}}
|
|
"{{.}}"
|
|
{{end}}
|
|
)
|
|
|
|
{{range .Functions}}
|
|
func Test{{.Name}}(t *testing.T) {
|
|
// Test {{.Name}} function
|
|
{{if .HasContext}}ctx := context.Background(){{end}}
|
|
|
|
t.Run("basic functionality", func(t *testing.T) {
|
|
// TODO: Add test implementation
|
|
require.True(t, true)
|
|
})
|
|
|
|
t.Run("edge cases", func(t *testing.T) {
|
|
// TODO: Add edge case tests
|
|
require.True(t, true)
|
|
})
|
|
|
|
t.Run("error handling", func(t *testing.T) {
|
|
// TODO: Add error handling tests
|
|
require.True(t, true)
|
|
})
|
|
}
|
|
|
|
func Test{{.Name}}_Concurrent(t *testing.T) {
|
|
// Test concurrent execution
|
|
var wg sync.WaitGroup
|
|
for i := 0; i < 10; i++ {
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
// TODO: Add concurrent test
|
|
}()
|
|
}
|
|
wg.Wait()
|
|
}
|
|
|
|
func Benchmark{{.Name}}(b *testing.B) {
|
|
{{if .HasContext}}ctx := context.Background(){{end}}
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
// TODO: Add benchmark
|
|
}
|
|
}
|
|
{{end}}
|
|
|
|
{{range .Types}}
|
|
func Test{{.Name}}(t *testing.T) {
|
|
// Test {{.Name}} type
|
|
t.Run("creation", func(t *testing.T) {
|
|
// TODO: Test type creation
|
|
require.True(t, true)
|
|
})
|
|
|
|
{{range .Methods}}
|
|
t.Run("{{.Name}}", func(t *testing.T) {
|
|
// Test {{.Name}} method
|
|
require.True(t, true)
|
|
})
|
|
{{end}}
|
|
}
|
|
|
|
func Test{{.Name}}_Concurrent(t *testing.T) {
|
|
// Test concurrent access to {{.Name}}
|
|
var wg sync.WaitGroup
|
|
for i := 0; i < 100; i++ {
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
// TODO: Add concurrent test
|
|
}()
|
|
}
|
|
wg.Wait()
|
|
}
|
|
{{end}}
|
|
|
|
{{range .Interfaces}}
|
|
func Test{{.Name}}Interface(t *testing.T) {
|
|
// Test {{.Name}} interface implementation
|
|
t.Run("mock implementation", func(t *testing.T) {
|
|
// TODO: Test mock implementation
|
|
require.True(t, true)
|
|
})
|
|
|
|
{{range .Methods}}
|
|
t.Run("{{.Name}}", func(t *testing.T) {
|
|
// Test {{.Name}} method
|
|
require.True(t, true)
|
|
})
|
|
{{end}}
|
|
}
|
|
{{end}}
|
|
|
|
// Integration tests
|
|
func TestIntegration(t *testing.T) {
|
|
t.Run("full workflow", func(t *testing.T) {
|
|
// TODO: Add integration test
|
|
require.True(t, true)
|
|
})
|
|
}
|
|
|
|
// Race condition tests
|
|
func TestRaceConditions(t *testing.T) {
|
|
// Run with: go test -race
|
|
t.Run("concurrent access", func(t *testing.T) {
|
|
// TODO: Add race condition test
|
|
require.True(t, true)
|
|
})
|
|
}
|
|
`
|
|
|
|
type TestFile struct {
|
|
Package string
|
|
Imports []string
|
|
Functions []Function
|
|
Types []Type
|
|
Interfaces []Interface
|
|
}
|
|
|
|
type Function struct {
|
|
Name string
|
|
HasContext bool
|
|
HasError bool
|
|
}
|
|
|
|
type Type struct {
|
|
Name string
|
|
Methods []Method
|
|
}
|
|
|
|
type Interface struct {
|
|
Name string
|
|
Methods []Method
|
|
}
|
|
|
|
type Method struct {
|
|
Name string
|
|
}
|
|
|
|
func main() {
|
|
err := filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Skip test files, vendor, and cmd directories
|
|
if strings.Contains(path, "_test.go") ||
|
|
strings.Contains(path, "/vendor/") ||
|
|
strings.Contains(path, "/cmd/") ||
|
|
strings.Contains(path, ".git") ||
|
|
!strings.HasSuffix(path, ".go") {
|
|
return nil
|
|
}
|
|
|
|
// Parse the Go file
|
|
fset := token.NewFileSet()
|
|
node, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
|
|
if err != nil {
|
|
return nil // Skip files that can't be parsed
|
|
}
|
|
|
|
// Check if test file already exists
|
|
testPath := strings.TrimSuffix(path, ".go") + "_test.go"
|
|
if _, err := os.Stat(testPath); err == nil {
|
|
// Test file exists, check if it needs improvement
|
|
testContent, _ := ioutil.ReadFile(testPath)
|
|
if len(testContent) < 500 { // If test file is too small
|
|
fmt.Printf("Improving test file: %s\n", testPath)
|
|
generateTestFile(node, testPath)
|
|
}
|
|
} else {
|
|
// Test file doesn't exist, create it
|
|
fmt.Printf("Creating test file: %s\n", testPath)
|
|
generateTestFile(node, testPath)
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
if err != nil {
|
|
fmt.Printf("Error walking files: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func generateTestFile(node *ast.File, testPath string) {
|
|
testData := TestFile{
|
|
Package: node.Name.Name,
|
|
Imports: []string{},
|
|
}
|
|
|
|
// Collect imports
|
|
imports := make(map[string]bool)
|
|
for _, imp := range node.Imports {
|
|
if imp.Path != nil {
|
|
path := strings.Trim(imp.Path.Value, `"`)
|
|
if !strings.Contains(path, "testing") && !strings.Contains(path, "testify") {
|
|
imports[path] = true
|
|
}
|
|
}
|
|
}
|
|
for imp := range imports {
|
|
testData.Imports = append(testData.Imports, imp)
|
|
}
|
|
|
|
// Analyze declarations
|
|
for _, decl := range node.Decls {
|
|
switch d := decl.(type) {
|
|
case *ast.FuncDecl:
|
|
if d.Recv == nil && ast.IsExported(d.Name.Name) {
|
|
// Top-level function
|
|
fn := Function{
|
|
Name: d.Name.Name,
|
|
HasContext: hasContextParam(d.Type),
|
|
HasError: hasErrorReturn(d.Type),
|
|
}
|
|
testData.Functions = append(testData.Functions, fn)
|
|
}
|
|
case *ast.GenDecl:
|
|
for _, spec := range d.Specs {
|
|
switch s := spec.(type) {
|
|
case *ast.TypeSpec:
|
|
if ast.IsExported(s.Name.Name) {
|
|
switch st := s.Type.(type) {
|
|
case *ast.StructType:
|
|
// Struct type
|
|
typ := Type{Name: s.Name.Name}
|
|
// Find methods for this type
|
|
for _, decl := range node.Decls {
|
|
if fn, ok := decl.(*ast.FuncDecl); ok && fn.Recv != nil {
|
|
if isMethodOf(fn, s.Name.Name) {
|
|
typ.Methods = append(typ.Methods, Method{Name: fn.Name.Name})
|
|
}
|
|
}
|
|
}
|
|
testData.Types = append(testData.Types, typ)
|
|
case *ast.InterfaceType:
|
|
// Interface type
|
|
iface := Interface{Name: s.Name.Name}
|
|
for _, method := range st.Methods.List {
|
|
if len(method.Names) > 0 {
|
|
iface.Methods = append(iface.Methods, Method{Name: method.Names[0].Name})
|
|
}
|
|
}
|
|
testData.Interfaces = append(testData.Interfaces, iface)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Generate test file
|
|
tmpl, err := template.New("test").Parse(testTemplate)
|
|
if err != nil {
|
|
fmt.Printf("Error parsing template: %v\n", err)
|
|
return
|
|
}
|
|
|
|
file, err := os.Create(testPath)
|
|
if err != nil {
|
|
fmt.Printf("Error creating test file %s: %v\n", testPath, err)
|
|
return
|
|
}
|
|
defer file.Close()
|
|
|
|
err = tmpl.Execute(file, testData)
|
|
if err != nil {
|
|
fmt.Printf("Error executing template for %s: %v\n", testPath, err)
|
|
}
|
|
}
|
|
|
|
func hasContextParam(ft *ast.FuncType) bool {
|
|
if ft.Params == nil {
|
|
return false
|
|
}
|
|
for _, param := range ft.Params.List {
|
|
if sel, ok := param.Type.(*ast.SelectorExpr); ok {
|
|
if ident, ok := sel.X.(*ast.Ident); ok && ident.Name == "context" {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func hasErrorReturn(ft *ast.FuncType) bool {
|
|
if ft.Results == nil {
|
|
return false
|
|
}
|
|
for _, result := range ft.Results.List {
|
|
if ident, ok := result.Type.(*ast.Ident); ok && ident.Name == "error" {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func isMethodOf(fn *ast.FuncDecl, typeName string) bool {
|
|
if fn.Recv == nil || len(fn.Recv.List) == 0 {
|
|
return false
|
|
}
|
|
recv := fn.Recv.List[0]
|
|
switch t := recv.Type.(type) {
|
|
case *ast.Ident:
|
|
return t.Name == typeName
|
|
case *ast.StarExpr:
|
|
if ident, ok := t.X.(*ast.Ident); ok {
|
|
return ident.Name == typeName
|
|
}
|
|
}
|
|
return false
|
|
} |