Skip to content

Commit

Permalink
feat(kernel): define guardian decoration order (#73)
Browse files Browse the repository at this point in the history
  • Loading branch information
plastikfan committed Jul 9, 2024
1 parent 75e93d4 commit f085eb1
Show file tree
Hide file tree
Showing 24 changed files with 520 additions and 148 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
"watchv",
"watchvc",
"watchvi",
"Wrapf"
"Wrapf",
"xcol"
]
}
4 changes: 4 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ tasks:
cmds:
- go test ./i18n

toc:
cmds:
- go test ./collections

tp:
cmds:
- go test ./pref
Expand Down
26 changes: 18 additions & 8 deletions builders.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
package tv

import (
"github.com/snivilised/traverse/enums"
"github.com/snivilised/traverse/internal/kernel"
"github.com/snivilised/traverse/internal/lo"
"github.com/snivilised/traverse/internal/types"
"github.com/snivilised/traverse/measure"
"github.com/snivilised/traverse/pref"
)

type buildArtefacts struct {
o *pref.Options
kc types.KernelController
plugins []types.Plugin
ext extent
o *pref.Options
kc types.KernelController
plugins []types.Plugin
activeRoles []enums.Role
ext extent
}

type Builders struct {
Expand Down Expand Up @@ -73,6 +76,12 @@ func (bs *Builders) buildAll() (*buildArtefacts, error) {

// INIT PLUGINS
//
roles := lo.Map(plugins, func(plugin types.Plugin, _ int) enums.Role {
return plugin.Role()
})

artefacts.Mediator.Arrange(roles)

for _, p := range plugins {
if bindErr := p.Init(); bindErr != nil {
return &buildArtefacts{
Expand All @@ -85,9 +94,10 @@ func (bs *Builders) buildAll() (*buildArtefacts, error) {
}

return &buildArtefacts{
o: o,
kc: artefacts.Kontroller,
plugins: plugins,
ext: ext,
o: o,
kc: artefacts.Kontroller,
plugins: plugins,
activeRoles: roles,
ext: ext,
}, nil
}
13 changes: 13 additions & 0 deletions collections/collections-suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package collections_test

import (
"testing"

. "github.com/onsi/ginkgo/v2" //nolint:revive // ok
. "github.com/onsi/gomega" //nolint:revive // ok
)

func TestCollections(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Collections Suite")
}
110 changes: 110 additions & 0 deletions collections/positional-set.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package collections

import (
"github.com/snivilised/traverse/internal/lo"
"golang.org/x/exp/constraints"
)

type Orderable interface {
constraints.Integer | string
}

type PositionalSet[T Orderable] struct {
order []T // Defines the valid elements and their order
items map[T]bool // Tracks which items are in the set
positions map[T]int // Maps each item to its position in the order
anchor T
}

func NewPositionalSet[T Orderable](order []T, anchor T) *PositionalSet[T] {
o := lo.Reject(lo.Uniq(order), func(
item T, _ int,
) bool {
return item == anchor
})
o = append(o, anchor)

ps := &PositionalSet[T]{
order: o,
items: make(map[T]bool),
positions: make(map[T]int),
anchor: anchor,
}

for i, item := range o {
ps.positions[item] = i
}
ps.items[anchor] = true

return ps
}

// Insert adds an item to the set if it's in the order and is not present
func (ps *PositionalSet[T]) Insert(item T) bool {
if item == ps.anchor {
return false
}

if _, exists := ps.positions[item]; exists {
if _, found := ps.items[item]; found {
return false
}
ps.items[item] = true
return true
}

return false
}

// Add insert multiple items into the set under the same conditions as
// Insert
func (ps *PositionalSet[T]) All(items ...T) bool {
result := true

for _, item := range items {
inserted := ps.Insert(item)

if result {
result = inserted
}
}

return result
}

// Delete removes an item from the set
func (ps *PositionalSet[T]) Delete(item T) {
if item == ps.anchor {
return
}

ps.items[item] = false
delete(ps.items, item)
}

// Contains checks if an item is in the set
func (ps *PositionalSet[T]) Contains(item T) bool {
return ps.items[item]
}

// Items returns all items in the set, in the defined order
func (ps *PositionalSet[T]) Items() []T {
result := make([]T, 0, len(ps.items))
for _, item := range ps.order {
if ps.items[item] {
result = append(result, item)
}
}
return result
}

// Position returns the position of an item in the order
func (ps *PositionalSet[T]) Position(item T) (int, bool) {
pos, exists := ps.positions[item]
return pos, exists
}

// Count returns the elements in the set
func (ps *PositionalSet[T]) Count() int {
return len(ps.items)
}
193 changes: 193 additions & 0 deletions collections/positional-set_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
package collections_test

import (
"fmt"

. "github.com/onsi/ginkgo/v2" //nolint:revive // ok
. "github.com/onsi/gomega" //nolint:revive // ok

"github.com/snivilised/traverse/collections"
"github.com/snivilised/traverse/internal/helpers"
)

var (
rainbow = []string{"richard", "of", "york", "gave", "battle", "in", "vain"}
scrambled = []string{"york", "vain", "battle", "of", "richard", "gave", "in"}
)

func assertColoursAreInOrder(set *collections.PositionalSet[string]) {
anchor, _ := set.Position("ANCHOR")

for _, colour := range rainbow {
pos, _ := set.Position(colour)
Expect(pos < anchor).To(BeTrue(), helpers.Reason(
fmt.Sprintf("position(%v) of colour: %v should be less than anchor's(%v)",
pos, colour, anchor),
))
}
}

var _ = Describe("PositionalSet", func() {
type (
orderingStringTE struct {
given string
should string
roles []string
}
)

var (
set *collections.PositionalSet[string]
)

BeforeEach(func() {
set = collections.NewPositionalSet(rainbow, "ANCHOR")
})

Context("Count", func() {
When("no items added", func() {
It("🧪 should: contain just the anchor", func() {
Expect(set.Count()).To(Equal(1), helpers.Reason("only anchor should be present"))
})
})
})

Context("Insert", func() {
When("requested item is the anchor", func() {
It("🧪 should: not insert", func() {
Expect(set.Insert("ANCHOR")).To(BeFalse(), helpers.Reason("inserting anchor is invalid"))
Expect(set.Count()).To(Equal(1), helpers.Reason("only anchor should be present"))
})
})

When("valid item requested", func() {
It("🧪 should: insert", func() {
Expect(set.Insert("richard")).To(BeTrue(), helpers.Reason("richard is in order list"))
Expect(set.Count()).To(Equal(2), helpers.Reason("richard, anchor"))
})
})

When("valid item already present", func() {
It("🧪 should: not insert", func() {
set.Insert("richard")
Expect(set.Insert("richard")).To(BeFalse(), helpers.Reason("richard already in order list"))
Expect(set.Count()).To(Equal(2), helpers.Reason("richard, anchor"))
})
})

When("invalid item requested", func() {
It("🧪 should: not insert", func() {
Expect(set.Insert("gold")).To(BeFalse(), helpers.Reason("gold not in order list"))
Expect(set.Count()).To(Equal(1), helpers.Reason("only anchor should be present"))
})
})
})

Context("All", func() {
When("All valid items requested", func() {
It("🧪 should: insert all", func() {
Expect(set.All(
"richard", "of", "york", "gave", "battle", "in", "vain",
)).To(BeTrue(), helpers.Reason("all items are valid"))
Expect(set.Count()).To(Equal(8), helpers.Reason("should contain all items"))
})
})

When("Not all are valid", func() {
It("🧪 should: insert only valid", func() {
Expect(set.All(
"richard", "gold", "of", "silver", "york", "bronze",
)).To(BeFalse(), helpers.Reason("all items are valid"))
Expect(set.Count()).To(Equal(4), helpers.Reason("should contain valid items"))
})
})
})

Context("Delete", func() {
When("requested item is the anchor", func() {
It("🧪 should: not delete", func() {
set.Delete("ANCHOR")
Expect(set.Count()).To(Equal(1), helpers.Reason("anchor should still be present"))
})
})

When("requested valid item is present", func() {
It("🧪 should: delete", func() {
set.Insert("york")
set.Delete("york")
Expect(set.Count()).To(Equal(1), helpers.Reason("york should deleted"))
})
})

When("requested valid item is not present", func() {
It("🧪 should: not delete", func() {
set.Delete("york")
Expect(set.Count()).To(Equal(1), helpers.Reason("only anchor should be present"))
})
})

When("requested valid item is not valid", func() {
It("🧪 should: not delete", func() {
set.Delete("silver")
Expect(set.Count()).To(Equal(1), helpers.Reason("only anchor should be present"))
})
})
})

Context("Position", func() {
When("multiple items inserted in order", func() {
It("🧪 should: return position less than anchor", func() {
set.All(rainbow...)
assertColoursAreInOrder(set)
})
})

When("multiple items inserted out of order", func() {
It("🧪 should: return position less than anchor", func() {
set.All(scrambled...)
assertColoursAreInOrder(set)
})

It("🧪 should: contain correct positions when colours compared", func() {
set.All(scrambled...)
richard, _ := set.Position("richard")
of, _ := set.Position("of")
york, _ := set.Position("york")
Expect(richard < of).To(BeTrue())
Expect(richard < york).To(BeTrue())
})
})
})

Context("Items", func() {
When("multiple items inserted in order", func() {
It("🧪 should: return items defined by order", func() {
set.All(rainbow...)
expected := append(append([]string{}, rainbow...), "ANCHOR")
Expect(set.Items()).To(HaveExactElements(expected))
})
})

When("multiple items inserted out of order", func() {
It("🧪 should: return items defined by order", func() {
set.All(scrambled...)
expected := append(append([]string{}, rainbow...), "ANCHOR")
Expect(set.Items()).To(HaveExactElements(expected))
})
})

When("partial items inserted in order", func() {
It("🧪 should: return items defined by order", func() {
set.All("vain", "battle", "york")
expected := []string{"york", "battle", "vain", "ANCHOR"}
Expect(set.Items()).To(HaveExactElements(expected))

set.Delete("battle")
set.Insert("of")

expected = []string{"of", "york", "vain", "ANCHOR"}
Expect(set.Items()).To(HaveExactElements(expected))
})
})
})
})
Loading

0 comments on commit f085eb1

Please sign in to comment.