jx/internal/client/client_test.go

324 lines
7.5 KiB
Go
Raw Permalink Normal View History

2024-09-24 19:26:40 +00:00
// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
package client
import (
"github.com/stretchr/testify/assert"
"os"
"os/user"
"os/exec"
"testing"
"decl/internal/tempdir"
"log"
"decl/internal/folio"
_ "decl/internal/fan"
"decl/internal/codec"
"decl/internal/data"
"decl/internal/ext"
2024-09-24 19:26:40 +00:00
"context"
"fmt"
"log/slog"
"archive/tar"
"compress/gzip"
"bytes"
"io"
2024-09-24 19:26:40 +00:00
)
var programLevel = new(slog.LevelVar)
var TempDir tempdir.Path = "jx_client"
var ProcessTestUserName string
var ProcessTestGroupName string
func TestMain(m *testing.M) {
LoggerConfig()
2024-09-25 04:41:26 +00:00
err := TempDir.Create()
2024-09-24 19:26:40 +00:00
if err != nil || TempDir == "" {
log.Fatal(err)
}
ProcessTestUserName, ProcessTestGroupName = ProcessUserName()
rc := m.Run()
TempDir.Remove()
os.Exit(rc)
}
func LoggerConfig() {
logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: programLevel}))
slog.SetDefault(logger)
programLevel.Set(slog.LevelDebug)
}
func ProcessUserName() (string, string) {
processUser, userErr := user.Current()
if userErr != nil {
panic(userErr)
}
processGroup, groupErr := user.LookupGroupId(processUser.Gid)
if groupErr != nil {
panic(groupErr)
}
return processUser.Username, processGroup.Name
}
func ExitError(e error) string {
if e != nil {
switch v := e.(type) {
case *exec.ExitError:
return string(v.Stderr)
default:
return e.Error()
}
}
return ""
}
// jx import <docuri>...
func TestClientImport(t *testing.T) {
c := NewClient()
assert.NotNil(t, c)
importDocuments := []string{
"file://../../examples/file.jx.yaml",
"file://../../examples/user.jx.yaml",
}
assert.Nil(t, c.Import(importDocuments))
for index, uri := range importDocuments {
u := folio.URI(uri)
r, readerErr := u.ContentReaderStream()
assert.Nil(t, readerErr)
assert.NotNil(t, r)
doc := folio.DocumentRegistry.NewDocument(folio.URI(uri))
assert.Nil(t, doc.LoadReader(r, codec.FormatYaml))
imported := c.Documents[index]
assert.NotNil(t, imported)
assert.Equal(t, uri, imported.GetURI())
assert.Equal(t, doc.Len(), imported.Len())
}
}
// jx import --resource <resource>
func TestClientImportResource(t *testing.T) {
ctx := context.Background()
c := NewClient()
assert.NotNil(t, c)
importResources := []string{
"file://../../COPYRIGHT",
}
for _, uri := range importResources {
assert.Nil(t, c.ImportResource(ctx, uri))
}
imported := c.Documents[0]
assert.NotNil(t, imported)
for _, uri := range importResources {
assert.NotNil(t, imported.(*folio.Document).GetResource(uri))
}
}
func TestClientEmit(t *testing.T) {
//ctx := context.Background()
c := NewClient()
assert.NotNil(t, c)
importDocuments := []string{
"file://../../examples/file.jx.yaml",
"file://../../examples/user.jx.yaml",
}
assert.Nil(t, c.Import(importDocuments))
targetFile := TempDir.FilePath("jx_emit_output.jx.yaml")
targetFileURI := fmt.Sprintf("file://%s", targetFile)
assert.Nil(t, c.SetOutput(targetFile))
assert.Nil(t, c.Emit())
assert.FileExists(t, targetFile)
u := folio.URI(targetFileURI)
r, readerErr := u.ContentReaderStream()
assert.Nil(t, readerErr)
assert.NotNil(t, r)
extractor, err := folio.DocumentRegistry.ConverterTypes.New(targetFileURI)
assert.Nil(t, err)
assert.NotNil(t, extractor)
targetResource, resErr := u.NewResource(nil)
assert.Nil(t, resErr)
docs, exErr := extractor.(data.ManyExtractor).ExtractMany(targetResource, nil)
assert.Nil(t, exErr)
assert.Equal(t, 2, len(docs))
assert.Equal(t, 1, docs[1].Len())
}
func BenchmarkClientSystemConfigurations(b *testing.B) {
assert.Nil(b, TempDir.Mkdir("benchconfig", 0700))
ConfDir := tempdir.Path(TempDir.FilePath("benchconfig"))
2024-09-25 04:41:26 +00:00
assert.Nil(b, ConfDir.CreateFile("cfg.jx.yaml", `
2024-09-24 19:26:40 +00:00
configurations:
- name: files
values:
prefix: /usr
2024-09-25 04:41:26 +00:00
`))
2024-09-24 19:26:40 +00:00
configDirURI := fmt.Sprintf("file://%s", ConfDir)
programLevel.Set(slog.LevelError)
b.Run("systemconfiguration", func(b *testing.B) {
for i := 0; i < b.N; i++ {
c := NewClient()
2024-09-25 04:41:26 +00:00
_ = c.SystemConfiguration(configDirURI)
2024-09-24 19:26:40 +00:00
}
})
programLevel.Set(slog.LevelDebug)
}
func TestClientSystemConfiguration(t *testing.T) {
c := NewClient()
assert.NotNil(t, c)
assert.Nil(t, TempDir.Mkdir("config", 0700))
ConfDir := tempdir.Path(TempDir.FilePath("config"))
2024-09-25 04:41:26 +00:00
assert.Nil(t, ConfDir.CreateFile("cfg.jx.yaml", `
2024-09-24 19:26:40 +00:00
configurations:
- name: files
values:
prefix: /usr
2024-09-25 04:41:26 +00:00
`))
2024-09-24 19:26:40 +00:00
//configDirURI := fmt.Sprintf("file://%s", ConfDir)
configErr := c.SystemConfiguration(string(ConfDir))
assert.Nil(t, configErr)
assert.NotNil(t, c.Config)
slog.Info("TestClientSystemConfiguration", "config", c.Config)
cfg := c.Config.GetConfig("files")
assert.NotNil(t, cfg)
value, valueErr := cfg.GetValue("prefix")
assert.Nil(t, valueErr)
assert.Equal(t, "/usr", value.(string))
2024-09-25 04:41:26 +00:00
}
func TestClientApply(t *testing.T) {
ctx := context.Background()
c := NewClient()
assert.NotNil(t, c)
assert.Nil(t, TempDir.Mkdir("apply", 0700))
ApplyDir := tempdir.Path(TempDir.FilePath("apply"))
DocSource := ApplyDir.FilePath("res.jx.yaml")
TestFile := ApplyDir.FilePath("testfile.txt")
assert.Nil(t, ApplyDir.CreateFile("res.jx.yaml", fmt.Sprintf(`
resources:
- type: file
transition: create
attributes:
path: %s
content: |
a test string
owner: %s
group: %s
mode: 0644
`, TestFile, ProcessTestUserName, ProcessTestGroupName)))
assert.Nil(t, c.Import([]string{DocSource}))
assert.Nil(t, c.LoadDocumentImports())
assert.Nil(t, c.Apply(ctx, false))
assert.FileExists(t, TestFile)
assert.Nil(t, c.Apply(ctx, true))
assert.NoFileExists(t, TestFile)
2024-09-24 19:26:40 +00:00
}
var tarArchiveBuffer bytes.Buffer
func TarArchive(compress bool) (err error) {
var fileWriter io.WriteCloser
if compress {
gz := gzip.NewWriter(&tarArchiveBuffer)
defer gz.Close()
fileWriter = gz
} else {
fileWriter = ext.WriteNopCloser(&tarArchiveBuffer)
}
tw := tar.NewWriter(fileWriter)
fileContent := "test file content"
if err = tw.WriteHeader(&tar.Header{
Name: "testfile",
Mode: 0600,
Size: int64(len(fileContent)),
}); err == nil {
_, err = tw.Write([]byte(fileContent))
}
tw.Close()
return
}
func TestClientConverters(t *testing.T) {
for _, v := range []struct { Expected data.TypeName; URI string } {
{ Expected: data.TypeName("dir"), URI: "file:///tmp" },
{ Expected: data.TypeName("http"), URI: "https://localhost/test" },
{ Expected: data.TypeName("iptable"), URI: "iptable://filter/INPUT" },
{ Expected: data.TypeName("jx"), URI: "file:///tmp/test.jx.yaml" },
{ Expected: data.TypeName("package"), URI: "package://" },
{ Expected: data.TypeName("container"), URI: "container://" },
{ Expected: data.TypeName("user"), URI: "user://" },
{ Expected: data.TypeName("group"), URI: "group://" },
{ Expected: data.TypeName("tar"), URI: "tar://" },
{ Expected: data.TypeName("tar"), URI: "file:///tmp/foo.tar" },
{ Expected: data.TypeName("tar"), URI: "file:///tmp/foo.tar.gz" },
{ Expected: data.TypeName("tar"), URI: "file:///tmp/foo.tgz" },
} {
c, e := folio.DocumentRegistry.ConverterTypes.New(v.URI)
assert.Nil(t, e)
assert.NotNil(t, c)
assert.Equal(t, v.Expected, c.Type())
}
}
func TestClientImportTar(t *testing.T) {
c := NewClient()
assert.NotNil(t, c)
e := TarArchive(true)
assert.Nil(t, e)
assert.Greater(t, tarArchiveBuffer.Len(), 0)
path, err := TempDir.CreateFileFromReader("test.tar.gz", &tarArchiveBuffer)
assert.Nil(t, err)
uri := fmt.Sprintf("file://%s", path)
d := folio.NewDeclaration()
assert.Nil(t, d.NewResource(&uri))
docs, importErr := c.ImportSource(uri)
assert.Nil(t, importErr)
assert.Greater(t, len(docs), 0)
}