Cleanup old tests; post test tweaks
This commit is contained in:
@@ -44,6 +44,7 @@ func TestGraphBuilder_Rel(t *testing.T) {
|
||||
}
|
||||
|
||||
g, err := bl.Build(ctx, rr...)
|
||||
g.invert()
|
||||
req.NoError(err)
|
||||
req.Len(g.nodes(), 1)
|
||||
|
||||
@@ -72,14 +73,14 @@ func TestGraphBuilder_Rel(t *testing.T) {
|
||||
req.NoError(err)
|
||||
req.Len(g.nodes(), 2)
|
||||
|
||||
a := g.nodes()[0]
|
||||
b := g.nodes()[1]
|
||||
a := g.resIndex[rr[0]]
|
||||
b := g.resIndex[rr[1]]
|
||||
req.Len(g.childNodes(a), 1)
|
||||
req.Equal(b, g.childNodes(a)[0])
|
||||
req.Empty(g.parentNodes(a))
|
||||
|
||||
req.Len(b.pp, 1)
|
||||
req.Equal(a, b.pp[0])
|
||||
req.Len(g.parentNodes(b), 1)
|
||||
req.Equal(a, g.parentNodes(b)[0])
|
||||
})
|
||||
|
||||
t.Run("cyclic node link; a -> b -> a", func(t *testing.T) {
|
||||
@@ -99,6 +100,7 @@ func TestGraphBuilder_Rel(t *testing.T) {
|
||||
}
|
||||
|
||||
g, err := bl.Build(ctx, rr...)
|
||||
g.invert()
|
||||
req.NoError(err)
|
||||
req.Len(g.nodes(), 2)
|
||||
|
||||
@@ -127,6 +129,7 @@ func TestGraphBuilder_Rel(t *testing.T) {
|
||||
}
|
||||
|
||||
g, err := bl.Build(ctx, rr...)
|
||||
g.invert()
|
||||
req.NoError(err)
|
||||
req.Len(g.nodes(), 1)
|
||||
|
||||
@@ -147,6 +150,7 @@ func TestGraphBuilder_Rel(t *testing.T) {
|
||||
}
|
||||
|
||||
g, err := bl.Build(ctx, rr...)
|
||||
g.invert()
|
||||
req.NoError(err)
|
||||
req.Len(g.nodes(), 1)
|
||||
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
package csv
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/csv"
|
||||
"errors"
|
||||
"github.com/cortezaproject/corteza-server/compose/types"
|
||||
"github.com/cortezaproject/corteza-server/pkg/envoy"
|
||||
"io"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
type (
|
||||
CsvDecoder struct{}
|
||||
|
||||
RecordIterator func(func(*types.Record) error) error
|
||||
|
||||
ComposeRecordNode struct {
|
||||
Walk RecordIterator
|
||||
|
||||
// Metafields for relationship management
|
||||
Mod *types.Module
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
ErrorNoCsvHeader = errors.New("csv decoder: no header")
|
||||
ErrorCsvHeaderMalformed = errors.New("csv decoder: header malformed")
|
||||
|
||||
// This strict regexp for field names will do for now.
|
||||
// Later we can add support for matching over field labels as well.
|
||||
headerRegexp, _ = regexp.Compile("^[A-Za-z][0-9A-Za-z_]*[A-Za-z0-9]$")
|
||||
)
|
||||
|
||||
func NewCsvDecoder() *CsvDecoder {
|
||||
return &CsvDecoder{}
|
||||
}
|
||||
|
||||
// A quick header field validator
|
||||
//
|
||||
// @note should we complicate it any further?
|
||||
func (c *CsvDecoder) validateHeader(header []string) error {
|
||||
for _, h := range header {
|
||||
if !headerRegexp.MatchString(h) {
|
||||
return ErrorCsvHeaderMalformed
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CsvDecoder) Decode(ctx context.Context, r io.Reader, filename string) ([]envoy.Node, error) {
|
||||
n := &envoy.ComposeRecordNode{}
|
||||
|
||||
// Determine base module for dependency resolution
|
||||
// -4 is to remove .csv ext
|
||||
//
|
||||
// @todo tweak this a bit
|
||||
modRes := filename[0 : len(filename)-4]
|
||||
mod := &types.Module{}
|
||||
mod.Handle = modRes
|
||||
mod.Name = modRes
|
||||
n.Mod = mod
|
||||
|
||||
// Prepare reader
|
||||
//
|
||||
// For optimization we reuse allocated memory; keep this in mind!
|
||||
cr := csv.NewReader(r)
|
||||
cr.ReuseRecord = true
|
||||
|
||||
// Get header
|
||||
hh, err := cr.Read()
|
||||
if err == io.EOF {
|
||||
return nil, ErrorNoCsvHeader
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
header := make([]string, 0, len(hh))
|
||||
for _, h := range hh {
|
||||
header = append(header, h)
|
||||
}
|
||||
|
||||
err = c.validateHeader(header)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Iterator function for providing records to be imported.
|
||||
// This doesn't do any validation; that should be handled by other layers.
|
||||
n.Walk = func(f func(*types.Record) error) error {
|
||||
for {
|
||||
record, err := cr.Read()
|
||||
if err == io.EOF {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rvs := make(types.RecordValueSet, 0)
|
||||
for i, h := range header {
|
||||
v := &types.RecordValue{}
|
||||
v.Name = h
|
||||
v.Value = record[i]
|
||||
|
||||
rvs = append(rvs, v)
|
||||
}
|
||||
|
||||
rec := &types.Record{}
|
||||
rec.Values = rvs
|
||||
|
||||
err = f(rec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return []envoy.Node{n}, nil
|
||||
}
|
||||
+7
-8
@@ -89,24 +89,23 @@ func (g *graph) markConflicting(n *node) {
|
||||
}
|
||||
|
||||
func (g *graph) Relink() {
|
||||
for _, n := range g.nn {
|
||||
n.cc = make(nodeSet, 0, len(n.cc))
|
||||
n.pp = make(nodeSet, 0, len(n.pp))
|
||||
}
|
||||
|
||||
for res := range g.resIndex {
|
||||
n := g.resIndex[res]
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
|
||||
refs := res.Refs()
|
||||
cc := g.childNodes(n)
|
||||
|
||||
for _, ref := range refs {
|
||||
// If it's already linked, skip it
|
||||
if cc.findByRef(ref) != nil {
|
||||
continue
|
||||
}
|
||||
for _, ref := range res.Refs() {
|
||||
// else find the node and link to it (if we can)
|
||||
m := g.nn.findByRef(ref)
|
||||
if m != nil {
|
||||
g.addChild(n, m)
|
||||
g.addParent(m, n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,14 +46,4 @@ func TestApplication_UnmarshalYAML(t *testing.T) {
|
||||
req.Equal("one", doc.applications[0].res.Name)
|
||||
req.Equal("two", doc.applications[1].res.Name)
|
||||
})
|
||||
|
||||
t.Run("application rbac", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
|
||||
doc, err := parseDocument("application_rbac")
|
||||
req.NoError(err)
|
||||
req.NotNil(doc)
|
||||
app := doc.applications[0]
|
||||
req.Len(app.rbac, 2)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -167,19 +167,26 @@ func (wrap *composeRecord) UnmarshalYAML(n *yaml.Node) (err error) {
|
||||
return nil
|
||||
|
||||
case "createdAt":
|
||||
return v.Decode(wrap.sysValues["createdAt"])
|
||||
wrap.sysValues["createdAt"] = v.Value
|
||||
return nil
|
||||
case "updatedAt":
|
||||
return v.Decode(wrap.sysValues["updatedAt"])
|
||||
wrap.sysValues["updatedAt"] = v.Value
|
||||
return nil
|
||||
case "deletedAt":
|
||||
return v.Decode(wrap.sysValues["deletedAt"])
|
||||
wrap.sysValues["deletedAt"] = v.Value
|
||||
return nil
|
||||
case "createdBy":
|
||||
return v.Decode(wrap.refUser["createdBy"])
|
||||
wrap.refUser["createdBy"] = v.Value
|
||||
return nil
|
||||
case "updatedBy":
|
||||
return v.Decode(wrap.refUser["updatedBy"])
|
||||
wrap.refUser["updatedBy"] = v.Value
|
||||
return nil
|
||||
case "deletedBy":
|
||||
return v.Decode(wrap.refUser["deletedBy"])
|
||||
wrap.refUser["deletedBy"] = v.Value
|
||||
return nil
|
||||
case "ownedBy":
|
||||
return v.Decode(wrap.refUser["ownedBy"])
|
||||
wrap.refUser["ownedBy"] = v.Value
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,11 @@ import (
|
||||
func TestComposeRecord_UnmarshalYAML(t *testing.T) {
|
||||
var (
|
||||
parseString = func(src string) (*composeRecord, error) {
|
||||
w := &composeRecord{}
|
||||
w := &composeRecord{
|
||||
values: make(map[string]string),
|
||||
sysValues: make(map[string]string),
|
||||
refUser: make(map[string]string),
|
||||
}
|
||||
return w, yaml.Unmarshal([]byte(src), w)
|
||||
}
|
||||
)
|
||||
@@ -21,19 +25,18 @@ func TestComposeRecord_UnmarshalYAML(t *testing.T) {
|
||||
w, err := parseString(``)
|
||||
req.NoError(err)
|
||||
req.NotNil(w)
|
||||
req.Nil(w.res)
|
||||
req.Empty(w.values)
|
||||
})
|
||||
|
||||
t.Run("empty", func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
|
||||
w, err := parseString(`{ values: { foo: bar }, createdBy: foo, updatedAt: 2020-10-10T10:10:00Z, deletedBy: user }`)
|
||||
w, err := parseString(`{ values: { foo: bar }, createdBy: foo, updatedAt: 2020-10-10T10:10:00Z }`)
|
||||
req.NoError(err)
|
||||
req.NotNil(w)
|
||||
req.NotNil(w.res)
|
||||
req.NotEmpty(w.res.Values)
|
||||
req.NotEmpty(w.res.UpdatedAt)
|
||||
req.Equal("bar", w.res.Values.Get("foo", 0).Value)
|
||||
req.NotEmpty(w.values)
|
||||
req.NotEmpty(w.sysValues)
|
||||
req.Equal("bar", w.values["foo"])
|
||||
})
|
||||
|
||||
t.Run("compose record file 1", func(t *testing.T) {
|
||||
@@ -45,16 +48,16 @@ func TestComposeRecord_UnmarshalYAML(t *testing.T) {
|
||||
req.NotNil(doc.compose)
|
||||
req.Len(doc.compose.Records, 3)
|
||||
|
||||
req.NotNil(doc.compose.Records[0].res)
|
||||
req.NotEmpty(doc.compose.Records[0].values)
|
||||
req.Equal("Department", doc.compose.Records[0].refModule)
|
||||
rec := doc.compose.Records[0].res
|
||||
req.Equal("Service", rec.Values.Get("Name", 0).Value)
|
||||
req.Equal("50", rec.Values.Get("HourCost", 0).Value)
|
||||
v := doc.compose.Records[0].values
|
||||
req.Equal("Service", v["Name"])
|
||||
req.Equal("50", v["HourCost"])
|
||||
|
||||
req.NotNil(doc.compose.Records[1].res)
|
||||
req.NotEmpty(doc.compose.Records[1].values)
|
||||
req.Equal("EmailTemplate", doc.compose.Records[1].refModule)
|
||||
|
||||
req.NotNil(doc.compose.Records[2].res)
|
||||
req.NotEmpty(doc.compose.Records[2].values)
|
||||
req.Equal("Settings", doc.compose.Records[2].refModule)
|
||||
|
||||
//req.NotNil(doc.compose.records[0].rbac)
|
||||
|
||||
Reference in New Issue
Block a user