mirror of https://github.com/knative/func.git
170 lines
4.5 KiB
Go
170 lines
4.5 KiB
Go
//go:build !integration
|
|
// +build !integration
|
|
|
|
package scaffolding
|
|
|
|
import (
|
|
"errors"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"knative.dev/func/pkg/filesystem"
|
|
|
|
. "knative.dev/func/pkg/testing"
|
|
)
|
|
|
|
// TestWrite_RuntimeErrors ensures that known runtimes which are not
|
|
// yet implemented return a "not yet available" message, and unrecognized
|
|
// runtimes state as much.
|
|
func TestWrite_RuntimeErrors(t *testing.T) {
|
|
tests := []struct {
|
|
Runtime string
|
|
Expected any
|
|
}{
|
|
{"go", nil},
|
|
{"python", nil},
|
|
{"rust", &ErrDetectorNotImplemented{}},
|
|
{"node", &ErrDetectorNotImplemented{}},
|
|
{"typescript", &ErrDetectorNotImplemented{}},
|
|
{"quarkus", &ErrDetectorNotImplemented{}},
|
|
{"java", &ErrDetectorNotImplemented{}},
|
|
{"other", &ErrRuntimeNotRecognized{}},
|
|
}
|
|
for _, test := range tests {
|
|
t.Run(test.Runtime, func(t *testing.T) {
|
|
// Since runtime validation during signature detection is the very first
|
|
// thing that occurs, we can elide most of the setup and pass zero
|
|
// values for source directory, output directory and invocation.
|
|
// This may need to be expanded in the event the Write function is
|
|
// expanded to have more preconditions.
|
|
err := Write("", "", test.Runtime, "", nil)
|
|
if test.Expected != nil && err == nil {
|
|
t.Fatalf("expected runtime %v to yield a detection error", test.Runtime)
|
|
}
|
|
if test.Expected != nil && !errors.As(err, test.Expected) {
|
|
t.Fatalf("did not receive expected error type for %v runtime.", test.Runtime)
|
|
}
|
|
t.Logf("ok: %v", err)
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestWrite ensures that the Write method writes Scaffolding to the given
|
|
// destination. This is a fairly shallow test. See the Scaffolding and
|
|
// Detector tests for more depth.
|
|
func TestWrite(t *testing.T) {
|
|
// The filesystem containing scaffolding is expected to conform to the
|
|
// structure:
|
|
// /[language]/scaffolding/["instanced"|"static"]-[invocation]
|
|
// ex:
|
|
// "./go/scaffolding/instanced-http/main.go"
|
|
cwd, err := os.Getwd()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
fs := filesystem.NewOsFilesystem(filepath.Join(cwd, "testdata", "testwrite"))
|
|
|
|
root, done := Mktemp(t)
|
|
defer done()
|
|
|
|
// Write out a test implementation that will result in the InstancedHTTP
|
|
// signature being detected.
|
|
impl := `
|
|
package f
|
|
|
|
type F struct{}
|
|
|
|
func New() *F { return nil }
|
|
`
|
|
err = os.WriteFile(filepath.Join(root, "f.go"), []byte(impl), os.ModePerm)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// The output destination for the scaffolding
|
|
out := filepath.Join(root, "out")
|
|
|
|
// Write Scaffolding to
|
|
err = Write(
|
|
out, // output directory
|
|
root, // source code location
|
|
"go", // Runtime
|
|
"", // optional invocation hint (http is the default)
|
|
fs) // The filesystem from which the scaffolding should be pulled
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Assert there exists a main.go (from the testdata scaffolding filesystem).
|
|
if _, err = os.Stat(filepath.Join(root, "out", "main.go")); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Assert there exists a symbolic link to the source code
|
|
root, err = filepath.EvalSymlinks(root) // dereference any current symlinks
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
target, err := filepath.EvalSymlinks(filepath.Join(out, "f"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if target != root {
|
|
t.Fatalf("scaffolding symlink should be:\n%v\n But got target:\n%v", root, target)
|
|
}
|
|
|
|
}
|
|
|
|
// TestWrite_ScaffoldingNotFound ensures that a typed error is returned
|
|
// when scaffolding is not found.
|
|
func TestWrite_ScaffoldingNotFound(t *testing.T) {
|
|
cwd, err := os.Getwd()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
fs := filesystem.NewOsFilesystem(filepath.Join(cwd, "testdata", "testnotfound"))
|
|
|
|
root, done := Mktemp(t)
|
|
defer done()
|
|
|
|
impl := `
|
|
package f
|
|
|
|
type F struct{}
|
|
|
|
func New() *F { return nil }
|
|
`
|
|
err = os.WriteFile(filepath.Join(root, "f.go"), []byte(impl), os.ModePerm)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
out := filepath.Join(root, "out")
|
|
|
|
err = Write(out, root, "go", "", fs)
|
|
if err == nil {
|
|
t.Fatal("did not receive expected error")
|
|
}
|
|
if !errors.Is(err, ErrScaffoldingNotFound) {
|
|
t.Fatalf("error received was not ErrScaffoldingNotFound. %v", err)
|
|
}
|
|
}
|
|
|
|
// TestNewScaffoldingError ensures that a scaffolding error wraps its
|
|
// underlying error such that callers can use errors.Is/As.
|
|
func TestNewScaffoldingError(t *testing.T) {
|
|
|
|
// exampleError that would come from something scaffolding employs to
|
|
// accomplish a task
|
|
var ExampleError = errors.New("example error")
|
|
|
|
err := ScaffoldingError{"some ExampleError", ExampleError}
|
|
|
|
if !errors.Is(err, ExampleError) {
|
|
t.Fatalf("type ScaffoldingError does not wrap errors.")
|
|
}
|
|
t.Logf("ok: %v", err)
|
|
|
|
}
|