update cli tests
Some checks failed
Lint / golangci-lint (push) Has been cancelled
Declarative Tests / test (push) Has been cancelled
Declarative Tests / build-fedora (push) Has been cancelled
Declarative Tests / build-ubuntu-focal (push) Has been cancelled

This commit is contained in:
Matthew Rich 2024-09-25 05:13:53 +00:00
parent 52c58ea436
commit 2bee7f6bea
5 changed files with 137 additions and 20 deletions

View File

@ -12,20 +12,24 @@ import (
"net/http"
"net/http/httptest"
"fmt"
"decl/tests/tempdir"
"archive/tar"
"io"
"log"
"bytes"
)
var TempDir string
var TempDir tempdir.Path = "testcli"
func TestMain(m *testing.M) {
var err error
TempDir, err = os.MkdirTemp("", "testcli")
err := TempDir.Create()
if err != nil || TempDir == "" {
slog.Error("TestMain()", "error", err)
slog.Error("Failed creating temp dir", "error", err)
}
rc := m.Run()
os.RemoveAll(TempDir)
TempDir.Remove()
os.Exit(rc)
}
@ -85,7 +89,7 @@ configurations:
http_pass: bar
`
configPath := fmt.Sprintf("%s/testconfig.yaml", TempDir)
configPath := fmt.Sprintf("%s/testconfig.jx.yaml", TempDir)
f, err := os.Create(configPath)
assert.Nil(t, err)
defer f.Close()
@ -99,3 +103,78 @@ configurations:
assert.Nil(t, cliErr)
slog.Info("TestConfigSource", "yaml", yaml)
}
func TestCliConfigCommand(t *testing.T) {
if _, e := os.Stat("./jx"); errors.Is(e, os.ErrNotExist) {
t.Skip("cli not built")
}
yaml, cliErr := exec.Command("./jx", "config", "file://examples/config/file.cfg.jx.yaml").Output()
if cliErr != nil {
slog.Info("Debug CLI error", "error", cliErr, "stderr", cliErr.(*exec.ExitError).Stderr)
}
assert.Nil(t, cliErr)
slog.Info("TestConfigCommand", "yaml", yaml)
assert.NotEqual(t, "", string(yaml))
assert.Greater(t, len(yaml), 0)
}
func TestCliImportPackageCommand(t *testing.T) {
if _, e := os.Stat("./jx"); errors.Is(e, os.ErrNotExist) {
t.Skip("cli not built")
}
yaml, cliErr := exec.Command("./jx", "import", "package://").Output()
if cliErr != nil {
slog.Info("Debug CLI error", "error", cliErr, "stderr", cliErr.(*exec.ExitError).Stderr)
}
assert.Nil(t, cliErr)
assert.NotEqual(t, "", string(yaml))
assert.Greater(t, len(yaml), 0)
}
func TestCliExportTar(t *testing.T) {
if _, e := os.Stat("./jx"); errors.Is(e, os.ErrNotExist) {
t.Skip("cli not built")
}
assert.Nil(t, TempDir.Mkdir("tar", 0755))
assert.Nil(t, TempDir.CreateFile("tar/foo", "data"))
assert.Nil(t, TempDir.CreateFile("tar/bar", "data"))
cmdArgs := []string{"import", "--output", "tar://-", fmt.Sprintf("file://%s/tar", TempDir)}
slog.Info("TestCliExportTar()", "cmd", cmdArgs)
cmd := exec.Command("./jx", cmdArgs...)
slog.Info("TestCliExportTar()", "cmd", cmd)
stderr, errerr := cmd.StderrPipe()
assert.Nil(t, errerr)
stdout, outerr := cmd.StdoutPipe()
assert.Nil(t, outerr)
assert.Nil(t, cmd.Start())
errOutput, _ := io.ReadAll(stderr)
tarData, _ := io.ReadAll(stdout)
assert.Nil(t, cmd.Wait())
slog.Info("TestCliExportTar()", "stderr", errOutput)
assert.Greater(t, len(tarData), 0)
tr := tar.NewReader(bytes.NewBuffer(tarData))
files := []string{fmt.Sprintf("%s/tar/foo", TempDir), fmt.Sprintf("%s/tar/bar", TempDir)}
for {
hdr, err := tr.Next()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
assert.Contains(t, files, hdr.Name)
contents, err := io.ReadAll(tr)
assert.Nil(t, err)
assert.Equal(t, []byte("data"), contents)
}
}

View File

@ -34,15 +34,15 @@ func Load(uri folio.URI) (documents []data.Document, err error) {
var extractor data.Converter
var sourceResource data.Resource
if extractor, err = folio.DocumentRegistry.ConverterTypes.New(string(uri)); err == nil {
slog.Info("Load() extractor", "error", err)
slog.Info("builtin.Load() extractor", "uri", uri, "error", err)
targetDeclaration := folio.NewDeclaration()
if err = targetDeclaration.NewResource((*string)(&uri)); err == nil {
slog.Info("Load() extract many", "resource", sourceResource, "error", err, "uri", uri, "extractor", extractor)
slog.Info("builtin.Load() extract many", "resource", sourceResource, "error", err, "uri", uri, "extractor", extractor)
sourceResource = targetDeclaration.Attributes
sourceResource.(data.FileResource).SetFS(documentFiles)
documents, err = extractor.(data.ManyExtractor).ExtractMany(sourceResource, nil)
slog.Info("Load() extract many", "resource", sourceResource, "error", err)
slog.Info("builtin.Load() extract many", "resource", sourceResource, "error", err)
}
}
return

View File

@ -10,11 +10,19 @@ import (
"embed"
"net/http"
"log/slog"
"decl/internal/folio"
)
//go:embed schemas/*.schema.json
var schemaFiles embed.FS
var schemaFilesUri folio.URI = "file://config/schemas/*.schema.json"
func init() {
folio.DocumentRegistry.Schemas[schemaFilesUri] = schemaFiles
folio.DocumentRegistry.DefaultSchema = schemaFilesUri
}
type Schema struct {
schema gojsonschema.JSONLoader
}
@ -40,6 +48,7 @@ func (s *Schema) Validate(source string) error {
for _, err := range result.Errors() {
schemaErrors.WriteString(err.String() + "\n")
}
schemaErrors.WriteString(source)
return errors.New(schemaErrors.String())
}
return nil

View File

@ -8,6 +8,8 @@ import (
"net/url"
"strings"
"path/filepath"
"log/slog"
"runtime/debug"
)
/*
@ -21,17 +23,18 @@ var (
ErrInvalidProduct = errors.New("Invalid product")
)
//type Name[Registry any] string //`json:"type"`
type Factory[Product comparable] func(*url.URL) Product
type RegistryTypeMap[Product comparable] map[string]Factory[Product]
//type Name[Registry any] string //`json:"type"`
type Types[Product comparable] struct {
registry RegistryTypeMap[Product]
contentTypes RegistryTypeMap[Product]
}
func New[Product comparable]() *Types[Product] {
return &Types[Product]{registry: make(map[string]Factory[Product])}
return &Types[Product]{registry: make(map[string]Factory[Product]), contentTypes: make(map[string]Factory[Product])}
}
func (t *Types[Product]) Register(names []string, factory Factory[Product]) {
@ -40,15 +43,24 @@ func (t *Types[Product]) Register(names []string, factory Factory[Product]) {
}
}
func (t *Types[Product]) RegisterContentType(contenttypes []string, factory Factory[Product]) {
for _,name := range contenttypes {
t.contentTypes[name] = factory
}
}
func (t *Types[Product]) FromExtension(path string) (Factory[Product], error) {
elements := strings.Split(path, ".")
numberOfElements := len(elements)
slog.Info("Types[Product].FromExtension()", "path", path, "elements", elements, "types", t.contentTypes, "stacktrace", string(debug.Stack()))
if numberOfElements > 2 {
if src := t.Get(strings.Join(elements[numberOfElements - 2: numberOfElements - 1], ".")); src != nil {
ext := strings.Join(elements[numberOfElements - 2: numberOfElements], ".")
slog.Info("Types[Product].FromExtension() - Lookup", "ext", ext, "stacktrace", string(debug.Stack()))
if src := t.GetContentType(ext); src != nil {
return src, nil
}
}
if src := t.Get(elements[numberOfElements - 1]); src != nil {
if src := t.GetContentType(elements[numberOfElements - 1]); src != nil {
return src, nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownType, path)
@ -57,10 +69,13 @@ func (t *Types[Product]) FromExtension(path string) (Factory[Product], error) {
func (t *Types[Product]) New(uri string) (result Product, err error) {
u, e := url.Parse(uri)
if u == nil || e != nil {
err = fmt.Errorf("%w: %s", ErrUnknownType, e)
err = fmt.Errorf("%w: %s %s", ErrUnknownType, e, uri)
return
}
return t.NewFromParsedURI(u)
}
func (t *Types[Product]) NewFromParsedURI(u *url.URL) (result Product, err error) {
if u.Scheme == "" {
u.Scheme = "file"
}
@ -68,13 +83,15 @@ func (t *Types[Product]) New(uri string) (result Product, err error) {
path := filepath.Join(u.Hostname(), u.Path)
if d, lookupErr := t.FromExtension(path); d != nil {
return d(u), lookupErr
} else {
slog.Info("Types[Product].NewFromParsedURI() - FromExtension()", "uri", u, "path", path, "error", lookupErr, "stacktrace", string(debug.Stack()))
}
if r, ok := t.registry[u.Scheme]; ok {
if result = r(u); result != any(nil) {
return result, nil
} else {
return result, fmt.Errorf("%w: factory failed creating %s", ErrInvalidProduct, uri)
return result, fmt.Errorf("%w: factory failed creating %s", ErrInvalidProduct, u.String())
}
}
err = fmt.Errorf("%w: %s", ErrUnknownType, u.Scheme)
@ -88,8 +105,15 @@ func (t *Types[Product]) Has(typename string) bool {
return false
}
func (t *Types[Product]) Get(typename string) Factory[Product] {
if d, ok := t.registry[typename]; ok {
func (t *Types[Product]) HasContentType(contenttype string) bool {
if _, ok := t.contentTypes[contenttype]; ok {
return true
}
return false
}
func (t *Types[Product]) GetContentType(contenttype string) Factory[Product] {
if d, ok := t.contentTypes[contenttype]; ok {
return d
}
return nil

View File

@ -24,6 +24,7 @@ type MockContainerClient struct {
InjectContainerStop func(context.Context, string, container.StopOptions) error
InjectContainerWait func(ctx context.Context, containerID string, condition container.WaitCondition) (<-chan container.WaitResponse, <-chan error)
InjectImagePull func(ctx context.Context, refStr string, options image.PullOptions) (io.ReadCloser, error)
InjectImagePush func(ctx context.Context, image string, options image.PushOptions) (io.ReadCloser, error)
InjectImageInspectWithRaw func(ctx context.Context, imageID string) (types.ImageInspect, []byte, error)
InjectImageRemove func(ctx context.Context, imageID string, options image.RemoveOptions) ([]image.DeleteResponse, error)
InjectImageBuild func(ctx context.Context, buildContext io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error)
@ -42,6 +43,10 @@ func (m *MockContainerClient) ImagePull(ctx context.Context, refStr string, opti
return m.InjectImagePull(ctx, refStr, options)
}
func (m *MockContainerClient) ImagePush(ctx context.Context, image string, options image.PushOptions) (io.ReadCloser, error) {
return m.InjectImagePush(ctx, image, options)
}
func (m *MockContainerClient) ImageBuild(ctx context.Context, buildContext io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) {
return m.InjectImageBuild(ctx, buildContext, options)
}