Skip to content

Commit

Permalink
Merge pull request #4 from thediveo/develop
Browse files Browse the repository at this point in the history
feature: plugin group backup and restore
  • Loading branch information
thediveo authored Jan 4, 2024
2 parents c6a032a + bcd273f commit ca6949a
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 27 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/buildandtest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
go: [ '1.20', '1.19' ]
go: [ 'stable', 'oldstable' ]

steps:
- name: Set up Go ${{matrix.go}}
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,14 @@ plugger.Group[fooFn]().Register(foo)
// plugger.WithGroup("group"), plugger.WithSymbol(foo))
```

## In Unit Tests

Sometimes, unit tests need a well-defined isolated plugin group configuration.
For this, `PluginGroup[T]` objects as returned by `Group[T]()` can now be backed
up and restored using `PluginGroup[T].Backup()` and `PluginGroup[T].Restore()`.
Additionally, `PluginGroup[T].Clear()` resets a plugin group to its initial
empty state.

## VSCode Tasks

The included `go-plugger.code-workspace` defines the following tasks:
Expand Down
7 changes: 7 additions & 0 deletions doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,5 +97,12 @@ them could be removed; this v1/v2 feature wasn't really used anyway.
// before, v2:
// plugger.Register(plugger.WithName("plug1"),
// plugger.WithGroup("group"), plugger.WithSymbol(foo))
# In Unit Tests
Sometimes, unit tests need a well-defined isolated plugin group configuration.
For this, [PluginGroup] objects returned by [Group]() can now be backed up and
restored using [PluginGroup.Backup] and [PluginGroup.Restore]. Additionally,
[PluginGroup.Clear] resets a plugin group to its initial empty state.
*/
package plugger
16 changes: 8 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@ module github.com/thediveo/go-plugger/v3
go 1.19

require (
github.com/onsi/ginkgo/v2 v2.13.0
github.com/onsi/gomega v1.29.0
github.com/onsi/ginkgo/v2 v2.13.2
github.com/onsi/gomega v1.30.0
)

require (
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-logr/logr v1.3.0 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
golang.org/x/tools v0.14.0 // indirect
golang.org/x/tools v0.16.0 // indirect
)

require (
github.com/google/go-cmp v0.6.0 // indirect
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
golang.org/x/net v0.17.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc
golang.org/x/net v0.19.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
34 changes: 17 additions & 17 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
Expand All @@ -14,27 +14,27 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg=
github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/onsi/ginkgo/v2 v2.13.2 h1:Bi2gGVkfn6gQcjNjZJVO8Gf0FHzMPf2phUei9tejVMs=
github.com/onsi/ginkgo/v2 v2.13.2/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM=
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc h1:ao2WRsKSzW6KuUY9IWPwWahcHCgR0s52IfwutMfEbdM=
golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM=
golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
39 changes: 38 additions & 1 deletion group.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ type PluginGroup[T any] struct {
symbols []Symbol[T] // (ordered) list of registered plugin symbols.
}

// GroupStash is a “backup” of a PluginGroup. It can be used especially in
// unit tests where a PluginGroup needs to be modified to a particular known
// configuration for a test, and the group's original configuration restored
// after the test.
type GroupStash[T any] struct {
ordered bool
symbols []Symbol[T]
}

// Group returns the [*PluginGroup] object for the given exposed symbol type T.
// Calling Group multiple times for the same exposed symbol type T always
// returns the same [PluginGroup] object.
Expand All @@ -52,7 +61,7 @@ func Group[T any]() *PluginGroup[T] {

// groups maps function and interface types to their (typed) plugin groups.
var groupsmu sync.Mutex
var groups = map[reflect.Type]any{}
var groups = map[reflect.Type]any{} // actually, *PluginGroup[T]

// String renders a textual representation of a particular Group, showing the
// managed symbol type as well as the plugin-exposed symbols registered in this
Expand Down Expand Up @@ -174,6 +183,34 @@ func (g *PluginGroup[T]) Plugins() []string {
return plugins
}

// Clears this plugin group's configuration (such as in unit tests).
func (g *PluginGroup[T]) Clear() {
g.mu.Lock()
defer g.mu.Unlock()
g.ordered = false
g.symbols = nil
}

// Save returns a copy of this plugin group's current plugin configuration, for
// later restoration using the Restore method.
func (g *PluginGroup[T]) Backup() GroupStash[T] {
g.mu.RLock()
defer g.mu.RUnlock()
return GroupStash[T]{
ordered: g.ordered,
symbols: slices.Clone(g.symbols),
}
}

// Restore a plugin group's former plugin configuration from a backup previously
// created by the Backup method.
func (g *PluginGroup[T]) Restore(s GroupStash[T]) {
g.mu.Lock()
defer g.mu.Unlock()
g.ordered = s.ordered
g.symbols = slices.Clone(s.symbols)
}

// sort the plugins by name and optionally by reference; that is, individual
// plugins can claim to get to the front/end, or before/after a another named
// plugin. This method must be called under write lock.
Expand Down
26 changes: 26 additions & 0 deletions group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,30 @@ var _ = Describe("exposed plugin symbol groups", func() {
[]string{"alpha", "beta", "gamma"}),
)

It("backs up and restores", func() {
g := Group[fooFn]()
Expect(g).NotTo(BeNil())
g.Register(func() string { return "one" }, WithPlugin("one"))
g.Register(func() string { return "two" }, WithPlugin("two"), WithPlacement("<one"))

backup := g.Backup()
Expect(backup).NotTo(BeZero())

g.mu.Lock()
g.symbols[0].Plugin = "foobar"
g.mu.Unlock()
Expect(g.Plugins()).To(ConsistOf("foobar", "two"))
pluginname := func(s Symbol[fooFn]) string { return s.Plugin }
Expect(backup.symbols).To(ConsistOf(
WithTransform(pluginname, Equal("one")),
WithTransform(pluginname, Equal("two")),
), "backup should not have been modified")

g.Clear()
g.Register(func() string { return "three" }, WithPlugin("three"))
Expect(g.Plugins()).To(ConsistOf("three"))
g.Restore(backup)
Expect(g.Plugins()).To(ConsistOf("two", "one"))
})

})

0 comments on commit ca6949a

Please sign in to comment.