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"
"net/http/httptest" "net/http/httptest"
"fmt" "fmt"
"decl/tests/tempdir"
"archive/tar"
"io"
"log"
"bytes"
) )
var TempDir string var TempDir tempdir.Path = "testcli"
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
var err error err := TempDir.Create()
TempDir, err = os.MkdirTemp("", "testcli")
if err != nil || TempDir == "" { if err != nil || TempDir == "" {
slog.Error("TestMain()", "error", err) slog.Error("Failed creating temp dir", "error", err)
} }
rc := m.Run() rc := m.Run()
os.RemoveAll(TempDir) TempDir.Remove()
os.Exit(rc) os.Exit(rc)
} }
@ -85,7 +89,7 @@ configurations:
http_pass: bar http_pass: bar
` `
configPath := fmt.Sprintf("%s/testconfig.yaml", TempDir) configPath := fmt.Sprintf("%s/testconfig.jx.yaml", TempDir)
f, err := os.Create(configPath) f, err := os.Create(configPath)
assert.Nil(t, err) assert.Nil(t, err)
defer f.Close() defer f.Close()
@ -99,3 +103,78 @@ configurations:
assert.Nil(t, cliErr) assert.Nil(t, cliErr)
slog.Info("TestConfigSource", "yaml", yaml) 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 extractor data.Converter
var sourceResource data.Resource var sourceResource data.Resource
if extractor, err = folio.DocumentRegistry.ConverterTypes.New(string(uri)); err == nil { 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() targetDeclaration := folio.NewDeclaration()
if err = targetDeclaration.NewResource((*string)(&uri)); err == nil { 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 = targetDeclaration.Attributes
sourceResource.(data.FileResource).SetFS(documentFiles) sourceResource.(data.FileResource).SetFS(documentFiles)
documents, err = extractor.(data.ManyExtractor).ExtractMany(sourceResource, nil) 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 return

View File

@ -10,11 +10,19 @@ import (
"embed" "embed"
"net/http" "net/http"
"log/slog" "log/slog"
"decl/internal/folio"
) )
//go:embed schemas/*.schema.json //go:embed schemas/*.schema.json
var schemaFiles embed.FS 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 { type Schema struct {
schema gojsonschema.JSONLoader schema gojsonschema.JSONLoader
} }
@ -40,6 +48,7 @@ func (s *Schema) Validate(source string) error {
for _, err := range result.Errors() { for _, err := range result.Errors() {
schemaErrors.WriteString(err.String() + "\n") schemaErrors.WriteString(err.String() + "\n")
} }
schemaErrors.WriteString(source)
return errors.New(schemaErrors.String()) return errors.New(schemaErrors.String())
} }
return nil return nil

View File

@ -8,6 +8,8 @@ import (
"net/url" "net/url"
"strings" "strings"
"path/filepath" "path/filepath"
"log/slog"
"runtime/debug"
) )
/* /*
@ -21,17 +23,18 @@ var (
ErrInvalidProduct = errors.New("Invalid product") ErrInvalidProduct = errors.New("Invalid product")
) )
//type Name[Registry any] string //`json:"type"`
type Factory[Product comparable] func(*url.URL) Product type Factory[Product comparable] func(*url.URL) Product
type RegistryTypeMap[Product comparable] map[string]Factory[Product] type RegistryTypeMap[Product comparable] map[string]Factory[Product]
//type Name[Registry any] string //`json:"type"`
type Types[Product comparable] struct { type Types[Product comparable] struct {
registry RegistryTypeMap[Product] registry RegistryTypeMap[Product]
contentTypes RegistryTypeMap[Product]
} }
func New[Product comparable]() *Types[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]) { 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) { func (t *Types[Product]) FromExtension(path string) (Factory[Product], error) {
elements := strings.Split(path, ".") elements := strings.Split(path, ".")
numberOfElements := len(elements) numberOfElements := len(elements)
slog.Info("Types[Product].FromExtension()", "path", path, "elements", elements, "types", t.contentTypes, "stacktrace", string(debug.Stack()))
if numberOfElements > 2 { 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 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 src, nil
} }
return nil, fmt.Errorf("%w: %s", ErrUnknownType, path) 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) { func (t *Types[Product]) New(uri string) (result Product, err error) {
u, e := url.Parse(uri) u, e := url.Parse(uri)
if u == nil || e != nil { if u == nil || e != nil {
err = fmt.Errorf("%w: %s", ErrUnknownType, e) err = fmt.Errorf("%w: %s %s", ErrUnknownType, e, uri)
return return
} }
return t.NewFromParsedURI(u)
}
func (t *Types[Product]) NewFromParsedURI(u *url.URL) (result Product, err error) {
if u.Scheme == "" { if u.Scheme == "" {
u.Scheme = "file" 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) path := filepath.Join(u.Hostname(), u.Path)
if d, lookupErr := t.FromExtension(path); d != nil { if d, lookupErr := t.FromExtension(path); d != nil {
return d(u), lookupErr 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 r, ok := t.registry[u.Scheme]; ok {
if result = r(u); result != any(nil) { if result = r(u); result != any(nil) {
return result, nil return result, nil
} else { } 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) err = fmt.Errorf("%w: %s", ErrUnknownType, u.Scheme)
@ -88,8 +105,15 @@ func (t *Types[Product]) Has(typename string) bool {
return false return false
} }
func (t *Types[Product]) Get(typename string) Factory[Product] { func (t *Types[Product]) HasContentType(contenttype string) bool {
if d, ok := t.registry[typename]; ok { 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 d
} }
return nil return nil

View File

@ -24,6 +24,7 @@ type MockContainerClient struct {
InjectContainerStop func(context.Context, string, container.StopOptions) error InjectContainerStop func(context.Context, string, container.StopOptions) error
InjectContainerWait func(ctx context.Context, containerID string, condition container.WaitCondition) (<-chan container.WaitResponse, <-chan 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) 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) InjectImageInspectWithRaw func(ctx context.Context, imageID string) (types.ImageInspect, []byte, error)
InjectImageRemove func(ctx context.Context, imageID string, options image.RemoveOptions) ([]image.DeleteResponse, 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) 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) 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) { func (m *MockContainerClient) ImageBuild(ctx context.Context, buildContext io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) {
return m.InjectImageBuild(ctx, buildContext, options) return m.InjectImageBuild(ctx, buildContext, options)
} }