Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(kernel): define guardian decoration order (#73) #77

Merged
merged 1 commit into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading