From 9bdfd8e1b8ec2d6af20670751d739188dc90110a Mon Sep 17 00:00:00 2001 From: James Harris Date: Sat, 28 Nov 2020 19:29:45 +1000 Subject: [PATCH 1/2] Expose the `location` package. --- engine/internal/aggregate/controller.go | 2 +- engine/internal/aggregate/scope.go | 2 +- engine/internal/integration/scope.go | 2 +- engine/internal/panicx/unexpectedbehavior.go | 2 +- engine/internal/panicx/unexpectedmessage.go | 2 +- engine/internal/process/controller.go | 2 +- engine/internal/process/scope.go | 2 +- {internal/location => location}/doc.go | 0 {internal/location => location}/ginkgo_test.go | 0 .../location => location}/linenumber_test.go | 2 +- {internal/location => location}/location.go | 0 .../location => location}/location_test.go | 18 +++++++++--------- 12 files changed, 17 insertions(+), 17 deletions(-) rename {internal/location => location}/doc.go (100%) rename {internal/location => location}/ginkgo_test.go (100%) rename {internal/location => location}/linenumber_test.go (96%) rename {internal/location => location}/location.go (100%) rename {internal/location => location}/location_test.go (74%) diff --git a/engine/internal/aggregate/controller.go b/engine/internal/aggregate/controller.go index 6f02c68f..5e2f8a68 100644 --- a/engine/internal/aggregate/controller.go +++ b/engine/internal/aggregate/controller.go @@ -10,7 +10,7 @@ import ( "github.com/dogmatiq/testkit/engine/internal/panicx" "github.com/dogmatiq/testkit/envelope" "github.com/dogmatiq/testkit/fact" - "github.com/dogmatiq/testkit/internal/location" + "github.com/dogmatiq/testkit/location" ) // Controller is an implementation of engine.Controller for diff --git a/engine/internal/aggregate/scope.go b/engine/internal/aggregate/scope.go index abf26d6c..a04abaee 100644 --- a/engine/internal/aggregate/scope.go +++ b/engine/internal/aggregate/scope.go @@ -9,7 +9,7 @@ import ( "github.com/dogmatiq/testkit/engine/internal/panicx" "github.com/dogmatiq/testkit/envelope" "github.com/dogmatiq/testkit/fact" - "github.com/dogmatiq/testkit/internal/location" + "github.com/dogmatiq/testkit/location" ) // scope is an implementation of dogma.AggregateCommandScope. diff --git a/engine/internal/integration/scope.go b/engine/internal/integration/scope.go index 6530dbff..89c09a5e 100644 --- a/engine/internal/integration/scope.go +++ b/engine/internal/integration/scope.go @@ -9,7 +9,7 @@ import ( "github.com/dogmatiq/testkit/engine/internal/panicx" "github.com/dogmatiq/testkit/envelope" "github.com/dogmatiq/testkit/fact" - "github.com/dogmatiq/testkit/internal/location" + "github.com/dogmatiq/testkit/location" ) // scope is an implementation of dogma.IntegrationCommandScope. diff --git a/engine/internal/panicx/unexpectedbehavior.go b/engine/internal/panicx/unexpectedbehavior.go index 6446aef7..cb400413 100644 --- a/engine/internal/panicx/unexpectedbehavior.go +++ b/engine/internal/panicx/unexpectedbehavior.go @@ -5,7 +5,7 @@ import ( "github.com/dogmatiq/configkit" "github.com/dogmatiq/dogma" - "github.com/dogmatiq/testkit/internal/location" + "github.com/dogmatiq/testkit/location" ) // UnexpectedBehavior is a panic value that occurs when a handler exhibits some diff --git a/engine/internal/panicx/unexpectedmessage.go b/engine/internal/panicx/unexpectedmessage.go index 418c54fa..2602f809 100644 --- a/engine/internal/panicx/unexpectedmessage.go +++ b/engine/internal/panicx/unexpectedmessage.go @@ -5,7 +5,7 @@ import ( "github.com/dogmatiq/configkit" "github.com/dogmatiq/dogma" - "github.com/dogmatiq/testkit/internal/location" + "github.com/dogmatiq/testkit/location" ) // UnexpectedMessage is a panic value that provides more context when a handler diff --git a/engine/internal/process/controller.go b/engine/internal/process/controller.go index 8fd5a5a7..fbe7422d 100644 --- a/engine/internal/process/controller.go +++ b/engine/internal/process/controller.go @@ -12,7 +12,7 @@ import ( "github.com/dogmatiq/testkit/engine/internal/panicx" "github.com/dogmatiq/testkit/envelope" "github.com/dogmatiq/testkit/fact" - "github.com/dogmatiq/testkit/internal/location" + "github.com/dogmatiq/testkit/location" ) // Controller is an implementation of engine.Controller for diff --git a/engine/internal/process/scope.go b/engine/internal/process/scope.go index 07f64832..fadb442e 100644 --- a/engine/internal/process/scope.go +++ b/engine/internal/process/scope.go @@ -10,7 +10,7 @@ import ( "github.com/dogmatiq/testkit/engine/internal/panicx" "github.com/dogmatiq/testkit/envelope" "github.com/dogmatiq/testkit/fact" - "github.com/dogmatiq/testkit/internal/location" + "github.com/dogmatiq/testkit/location" ) // scope is an implementation of dogma.ProcessEventScope and diff --git a/internal/location/doc.go b/location/doc.go similarity index 100% rename from internal/location/doc.go rename to location/doc.go diff --git a/internal/location/ginkgo_test.go b/location/ginkgo_test.go similarity index 100% rename from internal/location/ginkgo_test.go rename to location/ginkgo_test.go diff --git a/internal/location/linenumber_test.go b/location/linenumber_test.go similarity index 96% rename from internal/location/linenumber_test.go rename to location/linenumber_test.go index d0d545a9..5304025a 100644 --- a/internal/location/linenumber_test.go +++ b/location/linenumber_test.go @@ -9,7 +9,7 @@ package location_test // imports statements added. import ( - . "github.com/dogmatiq/testkit/internal/location" + . "github.com/dogmatiq/testkit/location" // import padding // import padding // import padding diff --git a/internal/location/location.go b/location/location.go similarity index 100% rename from internal/location/location.go rename to location/location.go diff --git a/internal/location/location_test.go b/location/location_test.go similarity index 74% rename from internal/location/location_test.go rename to location/location_test.go index 70a36676..c50c2f8e 100644 --- a/internal/location/location_test.go +++ b/location/location_test.go @@ -1,7 +1,7 @@ package location_test import ( - . "github.com/dogmatiq/testkit/internal/location" + . "github.com/dogmatiq/testkit/location" . "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo/extensions/table" . "github.com/onsi/gomega" @@ -15,8 +15,8 @@ var _ = Describe("type Location", func() { Expect(loc).To(MatchAllFields( Fields{ - "Func": Equal("github.com/dogmatiq/testkit/internal/location_test.doNothing"), - "File": HaveSuffix("/internal/location/linenumber_test.go"), + "Func": Equal("github.com/dogmatiq/testkit/location_test.doNothing"), + "File": HaveSuffix("/location/linenumber_test.go"), "Line": Equal(50), }, )) @@ -35,8 +35,8 @@ var _ = Describe("type Location", func() { Expect(loc).To(MatchAllFields( Fields{ - "Func": Equal("github.com/dogmatiq/testkit/internal/location_test.ofMethodT.Method"), - "File": HaveSuffix("/internal/location/linenumber_test.go"), + "Func": Equal("github.com/dogmatiq/testkit/location_test.ofMethodT.Method"), + "File": HaveSuffix("/location/linenumber_test.go"), "Line": Equal(57), }, )) @@ -55,8 +55,8 @@ var _ = Describe("type Location", func() { Expect(loc).To(MatchAllFields( Fields{ - "Func": Equal("github.com/dogmatiq/testkit/internal/location_test.ofCallLayer2"), - "File": HaveSuffix("/internal/location/linenumber_test.go"), + "Func": Equal("github.com/dogmatiq/testkit/location_test.ofCallLayer2"), + "File": HaveSuffix("/location/linenumber_test.go"), "Line": Equal(53), }, )) @@ -71,8 +71,8 @@ var _ = Describe("type Location", func() { Expect(loc).To(MatchAllFields( Fields{ - "Func": Equal("github.com/dogmatiq/testkit/internal/location_test.doPanic"), - "File": HaveSuffix("/internal/location/linenumber_test.go"), + "Func": Equal("github.com/dogmatiq/testkit/location_test.doPanic"), + "File": HaveSuffix("/location/linenumber_test.go"), "Line": Equal(51), }, )) From 0003210f1d62ce35081b8bdab50c03e44564490d Mon Sep 17 00:00:00 2001 From: James Harris Date: Sat, 28 Nov 2020 19:41:40 +1000 Subject: [PATCH 2/2] Add `Action.Location()` method. --- CHANGELOG.md | 1 + action.advancetime.go | 11 ++++++- action.advancetime_test.go | 12 ++++++++ action.call.go | 18 +++++++++-- action.call_test.go | 12 ++++++++ action.dispatch.command_test.go | 12 ++++++++ action.dispatch.event_test.go | 12 ++++++++ action.dispatch.go | 22 +++++++++++--- action.go | 5 ++++ action.linenumber_test.go | 53 +++++++++++++++++++++++++++++++++ action_test.go | 2 ++ 11 files changed, 152 insertions(+), 8 deletions(-) create mode 100644 action.linenumber_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index db7c19c1..b8828071 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ should continue to work without modification. ### Added - **[BC]** Added `PredicateOptions` to `PredicateScope` +- **[BC]** Added `Action.Location()` method ### Changed diff --git a/action.advancetime.go b/action.advancetime.go index 5eef09f1..5378a53b 100644 --- a/action.advancetime.go +++ b/action.advancetime.go @@ -6,6 +6,7 @@ import ( "time" "github.com/dogmatiq/testkit/engine" + "github.com/dogmatiq/testkit/location" ) // AdvanceTime returns an Action that simulates the passage of time by advancing @@ -26,7 +27,10 @@ func AdvanceTime(adj TimeAdjustment) Action { panic("AdvanceTime(): adjustment must not be nil") } - return advanceTimeAction{adj} + return advanceTimeAction{ + adj, + location.OfCall(), + } } // A TimeAdjustment describes a change to the test's virtual clock. @@ -65,6 +69,7 @@ func ByDuration(d time.Duration) TimeAdjustment { // clock. type advanceTimeAction struct { adj TimeAdjustment + loc location.Location } func (a advanceTimeAction) Banner() string { @@ -74,6 +79,10 @@ func (a advanceTimeAction) Banner() string { ) } +func (a advanceTimeAction) Location() location.Location { + return a.loc +} + func (a advanceTimeAction) ConfigurePredicate(o *PredicateOptions) { } diff --git a/action.advancetime_test.go b/action.advancetime_test.go index 6b7d2a2e..1df53fcd 100644 --- a/action.advancetime_test.go +++ b/action.advancetime_test.go @@ -13,6 +13,7 @@ import ( "github.com/dogmatiq/testkit/internal/testingmock" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + . "github.com/onsi/gomega/gstruct" ) var _ = Describe("func AdvanceTime()", func() { @@ -91,6 +92,17 @@ var _ = Describe("func AdvanceTime()", func() { }).To(PanicWith("AdvanceTime(): adjustment must not be nil")) }) + It("captures the location that the action was created", func() { + act := advanceTime(ByDuration(10 * time.Second)) + Expect(act.Location()).To(MatchAllFields( + Fields{ + "Func": Equal("github.com/dogmatiq/testkit_test.advanceTime"), + "File": HaveSuffix("/action.linenumber_test.go"), + "Line": Equal(50), + }, + )) + }) + When("passed a ToTime() adjustment", func() { targetTime := time.Date(2100, 1, 2, 3, 4, 5, 6, time.UTC) diff --git a/action.call.go b/action.call.go index da03c280..a3ff7847 100644 --- a/action.call.go +++ b/action.call.go @@ -1,6 +1,10 @@ package testkit -import "context" +import ( + "context" + + "github.com/dogmatiq/testkit/location" +) // Call is an Action that invokes a user-defined function within the context of // a test. @@ -20,19 +24,27 @@ func Call(fn func()) Action { panic("Call(): function must not be nil") } - return callAction{fn} + return callAction{ + fn, + location.OfCall(), + } } // callAction is an implementation of Action that invokes a user-defined // function. type callAction struct { - fn func() + fn func() + loc location.Location } func (a callAction) Banner() string { return "CALLING USER-DEFINED FUNCTION" } +func (a callAction) Location() location.Location { + return a.loc +} + func (a callAction) ConfigurePredicate(o *PredicateOptions) { o.MatchDispatchCycleStartedFacts = true } diff --git a/action.call_test.go b/action.call_test.go index 24755e27..024109f0 100644 --- a/action.call_test.go +++ b/action.call_test.go @@ -16,6 +16,7 @@ import ( "github.com/dogmatiq/testkit/internal/testingmock" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + . "github.com/onsi/gomega/gstruct" ) var _ = Describe("func Call()", func() { @@ -186,4 +187,15 @@ var _ = Describe("func Call()", func() { Call(nil) }).To(PanicWith("Call(): function must not be nil")) }) + + It("captures the location that the action was created", func() { + act := call(func() {}) + Expect(act.Location()).To(MatchAllFields( + Fields{ + "Func": Equal("github.com/dogmatiq/testkit_test.call"), + "File": HaveSuffix("/action.linenumber_test.go"), + "Line": Equal(51), + }, + )) + }) }) diff --git a/action.dispatch.command_test.go b/action.dispatch.command_test.go index 2be91974..12550fd0 100644 --- a/action.dispatch.command_test.go +++ b/action.dispatch.command_test.go @@ -15,6 +15,7 @@ import ( "github.com/dogmatiq/testkit/internal/testingmock" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + . "github.com/onsi/gomega/gstruct" ) var _ = Describe("func ExecuteCommand()", func() { @@ -139,4 +140,15 @@ var _ = Describe("func ExecuteCommand()", func() { ExecuteCommand(nil) }).To(PanicWith("ExecuteCommand(): message must not be nil")) }) + + It("captures the location that the action was created", func() { + act := executeCommand(MessageC1) + Expect(act.Location()).To(MatchAllFields( + Fields{ + "Func": Equal("github.com/dogmatiq/testkit_test.executeCommand"), + "File": HaveSuffix("/action.linenumber_test.go"), + "Line": Equal(52), + }, + )) + }) }) diff --git a/action.dispatch.event_test.go b/action.dispatch.event_test.go index 4baa49b9..d9e4a21f 100644 --- a/action.dispatch.event_test.go +++ b/action.dispatch.event_test.go @@ -16,6 +16,7 @@ import ( "github.com/dogmatiq/testkit/internal/testingmock" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + . "github.com/onsi/gomega/gstruct" ) var _ = Describe("func RecordEvent()", func() { @@ -141,4 +142,15 @@ var _ = Describe("func RecordEvent()", func() { RecordEvent(nil) }).To(PanicWith("RecordEvent(): message must not be nil")) }) + + It("captures the location that the action was created", func() { + act := recordEvent(MessageE1) + Expect(act.Location()).To(MatchAllFields( + Fields{ + "Func": Equal("github.com/dogmatiq/testkit_test.recordEvent"), + "File": HaveSuffix("/action.linenumber_test.go"), + "Line": Equal(53), + }, + )) + }) }) diff --git a/action.dispatch.go b/action.dispatch.go index ce3507d3..4d1414fb 100644 --- a/action.dispatch.go +++ b/action.dispatch.go @@ -7,6 +7,7 @@ import ( "github.com/dogmatiq/configkit/message" "github.com/dogmatiq/dogma" "github.com/dogmatiq/testkit/internal/inflect" + "github.com/dogmatiq/testkit/location" ) // ExecuteCommand returns an Action that executes a command message. @@ -15,7 +16,11 @@ func ExecuteCommand(m dogma.Message) Action { panic(fmt.Sprintf("ExecuteCommand(%T): %s", m, err)) } - return dispatchAction{message.CommandRole, m} + return dispatchAction{ + message.CommandRole, + m, + location.OfCall(), + } } // RecordEvent returns an Action that records an event message. @@ -24,14 +29,19 @@ func RecordEvent(m dogma.Message) Action { panic(fmt.Sprintf("RecordEvent(%T): %s", m, err)) } - return dispatchAction{message.EventRole, m} + return dispatchAction{ + message.EventRole, + m, + location.OfCall(), + } } // dispatchAction is an implementation of Action that dispatches a message to // the engine. type dispatchAction struct { - r message.Role - m dogma.Message + r message.Role + m dogma.Message + loc location.Location } func (a dispatchAction) Banner() string { @@ -42,6 +52,10 @@ func (a dispatchAction) Banner() string { ) } +func (a dispatchAction) Location() location.Location { + return a.loc +} + func (a dispatchAction) ConfigurePredicate(o *PredicateOptions) { } diff --git a/action.go b/action.go index 5abe63e0..fc98536c 100644 --- a/action.go +++ b/action.go @@ -6,6 +6,7 @@ import ( "github.com/dogmatiq/configkit" "github.com/dogmatiq/testkit/engine" + "github.com/dogmatiq/testkit/location" ) // Action is an interface for any action that can be performed within a test. @@ -20,6 +21,10 @@ type Action interface { // for example "DOING ACTION". Banner() string + // Location returns the location within the code that the action was + // constructed. + Location() location.Location + // ConfigurePredicate updates o with any options required by the action. // // It is called before Do() when the action is used with Test.Expect(). diff --git a/action.linenumber_test.go b/action.linenumber_test.go new file mode 100644 index 00000000..aa9537fa --- /dev/null +++ b/action.linenumber_test.go @@ -0,0 +1,53 @@ +package testkit_test + +// This file contains definitions used within tests that check for specific line +// numbers. To minimize test disruption edit this file as infrequently as +// possible. +// +// New additions should always be made at the end so that the line numbers of +// existing definitions do not change. The padding below can be removed as +// imports statements added. + +import ( + "github.com/dogmatiq/dogma" + . "github.com/dogmatiq/testkit" + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding + // import padding +) + +func advanceTime(adj TimeAdjustment) Action { return AdvanceTime(adj) } +func call(fn func()) Action { return Call(fn) } +func executeCommand(m dogma.Message) Action { return ExecuteCommand(m) } +func recordEvent(m dogma.Message) Action { return RecordEvent(m) } diff --git a/action_test.go b/action_test.go index e30034ee..057da312 100644 --- a/action_test.go +++ b/action_test.go @@ -4,6 +4,7 @@ import ( "context" . "github.com/dogmatiq/testkit" + "github.com/dogmatiq/testkit/location" ) // noop is an Action that does nothing. @@ -16,5 +17,6 @@ type noopAction struct { } func (a noopAction) Banner() string { return "[NO-OP]" } +func (a noopAction) Location() location.Location { return location.Location{Func: ""} } func (a noopAction) ConfigurePredicate(*PredicateOptions) {} func (a noopAction) Do(ctx context.Context, s ActionScope) error { return a.err }