Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add compiler tests #73

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 69 additions & 48 deletions internal/bud/bud.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io"
"io/fs"
"os"
"os/exec"
"path/filepath"

"github.com/livebud/bud/internal/buildcache"
Expand All @@ -22,9 +23,24 @@ import (
)

func defaultEnv(module *gomod.Module) (Env, error) {
budPath, err := os.Executable()
// Lookup `bud` from the $PATH. Used instead of os.Executable() because
// when running tests, os.Executable() refers to the test package, leading
// to an infinite loop.
//
// WARNING: this can be out of sync with `bud/main.go`. You'll need to run
// `go install` if you make changes to `bud tool v8 client` or any of its
// dependencies.
//
// TODO: switch to passing the V8 client through a file pipe during
// development similar to how we're passing the TCP connection through
// the subprocesses.
budPath, err := exec.LookPath("bud")
if err != nil {
return nil, err
// Fallback to the current executable
budPath, err = os.Executable()
if err != nil {
return nil, err
}
}
return Env{
"HOME": os.Getenv("HOME"),
Expand Down Expand Up @@ -67,20 +83,49 @@ type Compiler struct {
ModCacheRW bool
}

// Load the overlay
func (c *Compiler) loadOverlay(ctx context.Context, module *gomod.Module) (fsys *overlay.FileSystem, err error) {
return overlay.Load(module)
func (c *Compiler) Compile(ctx context.Context, flag *bud.Flag) (p *Project, err error) {
// Load the overlay
overlay, err := c.loadOverlay(ctx, flag)
if err != nil {
return nil, err
}
// Sync the generators
if err := c.sync(ctx, overlay); err != nil {
return nil, err
}
// Write the import generator
if err := c.writeImporter(ctx, overlay); err != nil {
return nil, err
}
// Build the binary
if err := c.goBuild(ctx, c.module, filepath.Join("bud", "cli")); err != nil {
return nil, err
}
return &Project{
Module: c.module,
Env: c.Env,
Stdout: c.Stdout,
Stderr: c.Stderr,
}, nil
}

func (c *Compiler) writeImporter(ctx context.Context, overlay *overlay.FileSystem) error {
importFile, err := fs.ReadFile(overlay, "bud/import.go")
// Load the overlay
func (c *Compiler) loadOverlay(ctx context.Context, flag *bud.Flag) (fsys *overlay.FileSystem, err error) {
overlay, err := overlay.Load(c.module)
if err != nil {
return err
}
if err := c.module.DirFS().WriteFile("bud/import.go", importFile, 0644); err != nil {
return err
return nil, err
}
return nil
// Initialize dependencies
parser := parser.New(overlay, c.module)
injector := di.New(overlay, c.module, parser)
// Setup the generators
overlay.FileGenerator("bud/import.go", importfile.New(c.module))
overlay.FileGenerator("bud/.cli/main.go", mainfile.New(c.module))
overlay.FileGenerator("bud/.cli/program/program.go", program.New(flag, injector, c.module))
overlay.FileGenerator("bud/.cli/command/command.go", command.New(overlay, c.module, parser))
overlay.FileGenerator("bud/.cli/generator/generator.go", generator.New(overlay, c.module, parser))
overlay.FileGenerator("bud/.cli/transform/transform.go", transform.New(c.module))
return overlay, nil
}

// Sync the generators to bud/.cli
Expand All @@ -91,6 +136,18 @@ func (c *Compiler) sync(ctx context.Context, overlay *overlay.FileSystem) (err e
return nil
}

// Write the importer
func (c *Compiler) writeImporter(ctx context.Context, overlay *overlay.FileSystem) error {
importFile, err := fs.ReadFile(overlay, "bud/import.go")
if err != nil {
return err
}
if err := c.module.DirFS().WriteFile("bud/import.go", importFile, 0644); err != nil {
return err
}
return nil
}

// Build the CLI
func (c *Compiler) goBuild(ctx context.Context, module *gomod.Module, outPath string) (err error) {
// Ensure that main.go exists
Expand All @@ -106,39 +163,3 @@ func (c *Compiler) goBuild(ctx context.Context, module *gomod.Module, outPath st
}
return nil
}

func (c *Compiler) Compile(ctx context.Context, flag *bud.Flag) (p *Project, err error) {
// Load the overlay
overlay, err := c.loadOverlay(ctx, c.module)
if err != nil {
return nil, err
}
// Initialize dependencies
parser := parser.New(overlay, c.module)
injector := di.New(overlay, c.module, parser)
// Setup the generators
overlay.FileGenerator("bud/import.go", importfile.New(c.module))
overlay.FileGenerator("bud/.cli/main.go", mainfile.New(c.module))
overlay.FileGenerator("bud/.cli/program/program.go", program.New(flag, injector, c.module))
overlay.FileGenerator("bud/.cli/command/command.go", command.New(overlay, c.module, parser))
overlay.FileGenerator("bud/.cli/generator/generator.go", generator.New(overlay, c.module, parser))
overlay.FileGenerator("bud/.cli/transform/transform.go", transform.New(c.module))
// Sync the generators
if err := c.sync(ctx, overlay); err != nil {
return nil, err
}
// Write the import generator
if err := c.writeImporter(ctx, overlay); err != nil {
return nil, err
}
// Build the binary
if err := c.goBuild(ctx, c.module, filepath.Join("bud", "cli")); err != nil {
return nil, err
}
return &Project{
Module: c.module,
Env: c.Env,
Stdout: c.Stdout,
Stderr: c.Stderr,
}, nil
}
63 changes: 63 additions & 0 deletions internal/bud/bud_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package bud_test

import (
"context"
"fmt"
"os"
"path/filepath"
"testing"

"github.com/livebud/bud/package/gomod"

"github.com/livebud/bud/internal/bud"
"github.com/livebud/bud/internal/testdir"
runtime_bud "github.com/livebud/bud/runtime/bud"
"github.com/matryer/is"
)

func exists(paths ...string) error {
for _, path := range paths {
if _, err := os.Stat(path); err != nil {
return err
}
}
return nil
}

func notExists(paths ...string) error {
for _, path := range paths {
if _, err := os.Stat(path); nil == err {
return fmt.Errorf("%s exists but shouldn't", path)
}
}
return nil
}

func TestEmpty(t *testing.T) {
is := is.New(t)
dir := t.TempDir()
fmt.Println("loading dir")
td := testdir.New()
is.NoErr(td.Write(dir))
module, err := gomod.Find(dir)
is.NoErr(err)
fmt.Println("loaded")
fmt.Println("loading compiler")
compiler, err := bud.Load(module)
is.NoErr(err)
fmt.Println("loaded compiler")
ctx := context.Background()
fmt.Println("compiling")
project, err := compiler.Compile(ctx, &runtime_bud.Flag{
Hot: false,
Minify: true,
Embed: true,
})
is.NoErr(err)
is.NoErr(exists(filepath.Join(dir, "bud", "cli")))
is.NoErr(notExists(filepath.Join(dir, "bud", "app")))
_, err = project.Build(ctx)
is.NoErr(err)
is.NoErr(exists(filepath.Join(dir, "bud", "cli")))
is.NoErr(exists(filepath.Join(dir, "bud", "app")))
}
3 changes: 3 additions & 0 deletions internal/bud/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package bud

import (
"context"
"fmt"
"io"
"net"

Expand Down Expand Up @@ -47,9 +48,11 @@ func (p *Project) Builder(ctx context.Context) *exe.Cmd {

func (p *Project) Build(ctx context.Context) (*bud.App, error) {
cmd := p.Builder(ctx)
fmt.Println("running cmd")
if err := cmd.Run(); err != nil {
return nil, err
}
fmt.Println("ran cmd")
return &bud.App{
Module: p.Module,
Env: p.Env.List(),
Expand Down
6 changes: 3 additions & 3 deletions package/log/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ type Flusher interface {
Flush()
}

type Logger interface {
type Interface interface {
Debug(message string, args ...interface{})
Info(message string, args ...interface{})
Notice(message string, args ...interface{})
Expand Down Expand Up @@ -72,7 +72,7 @@ func WithPath(includePath bool) Option {
}

// New logger
func New(handler Handler, options ...Option) Logger {
func New(handler Handler, options ...Option) Interface {
logger := &logger{
Handler: handler,
includePath: false,
Expand Down Expand Up @@ -124,7 +124,7 @@ func (l *logger) keyValues(kvs ...interface{}) (list Fields) {
}

// New sub logger
func (l *logger) New(fields ...interface{}) Logger {
func (l *logger) New(fields ...interface{}) Interface {
return &logger{
Handler: l.Handler,
includePath: l.includePath,
Expand Down
7 changes: 7 additions & 0 deletions runtime/bud/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package bud

import (
"context"
"fmt"
"io"
"io/fs"
"os"
Expand Down Expand Up @@ -33,18 +34,24 @@ type Project struct {
}

func (c *Project) Compile(ctx context.Context, flag *Flag) (*App, error) {
fmt.Println("syncing app")
// Sync the app
if err := c.fsys.Sync("bud/.app"); err != nil {
return nil, err
}
fmt.Println("synced app")
fmt.Println("checking if main exists")
// Ensure that main.go exists
if _, err := fs.Stat(c.module, "bud/.app/main.go"); err != nil {
return nil, err
}
fmt.Println("checked if main exists")
// Build the binary
fmt.Println("building app")
if err := c.bcache.Build(ctx, c.module, "bud/.app/main.go", filepath.Join("bud", "app")); err != nil {
return nil, err
}
fmt.Println("built app")
return &App{
Module: c.module,
Env: c.Env,
Expand Down