Documentation ¶
Overview ¶
Example ¶
beforePatch := MyTimeFunc(2021, 2, 3, 4, 5, 6, 7) fmt.Printf("original: %v\n", beforePatch) patch := PatchFunc(MyTimeFunc, func(year, month, day, hour, min, sec, nsec int) time.Time { return time.Date(2001, 1, 1, 1, 1, 1, 1, time.UTC) }) duringPatch := MyTimeFunc(2021, 2, 3, 4, 5, 6, 7) fmt.Printf("patched: %v\n", duringPatch) patch.Delete() unpatched := MyTimeFunc(2021, 2, 3, 4, 5, 6, 7) fmt.Printf("unpatched: %v\n", unpatched) fmt.Printf("before AutoUnpatch\n") AutoUnpatch(func() { tmp := MyTimeFunc(2021, 2, 3, 4, 5, 6, 7) fmt.Printf("with AutoUnpatch, before mock: %v\n", tmp) // We can use `Return` to return specified values. Mock().Target(MyTimeFunc). Return(time.Date(2001, time.January, 1, 1, 1, 1, 1, time.UTC)). Build() tmp = MyTimeFunc(2021, 2, 3, 4, 5, 6, 7) fmt.Printf("with AutoUnpatch, after mock: %v\n", tmp) var innerFunc = func(year, month, day, hour, min, sec, nsec int) time.Time { return time.Date(2002, time.February, 2, 2, 2, 2, 2, time.UTC) } AutoUnpatch(func() { tmp := MyTimeFunc(2021, 2, 3, 4, 5, 6, 7) fmt.Printf("inner AutoUnpatch, before mock: %v\n", tmp) // We can also use `To` to specify a replacement function. Mock().Target(MyTimeFunc).To(innerFunc).Build() tmp = MyTimeFunc(2021, 2, 3, 4, 5, 6, 7) fmt.Printf("inner AutoUnpatch, after mock: %v\n", tmp) }) tmp = MyTimeFunc(2021, 2, 3, 4, 5, 6, 7) fmt.Printf("with AutoUnpatch, after inner: %v\n", tmp) // In AutoUnpatch, we can also use the Patch* functions. // Static function works. PatchFunc(MyTimeFunc, mock333) tmp = MyTimeFunc(2021, 2, 3, 4, 5, 6, 7) fmt.Printf("with AutoUnpatch, after inner mock333: %v\n", tmp) // Closure also works. var fakeTime = time.Date(2004, time.April, 4, 4, 4, 4, 4, time.UTC) var mock444 = func(year, month, day, hour, min, sec, nsec int) time.Time { return fakeTime } PatchFunc(MyTimeFunc, mock444) tmp = MyTimeFunc(2021, 2, 3, 4, 5, 6, 7) fmt.Printf("with AutoUnpatch, after inner mock444: %v\n", tmp) // We can also patch a function by name. Mock().ByName("github.com/jxskiss/gopkg/v2/monkey.MyTimeFunc", (func(year, month, day, hour, min, sec, nsec int) time.Time)(nil)). Return(time.Date(2005, time.May, 5, 5, 5, 5, 5, time.UTC)). Build() tmp = MyTimeFunc(2021, 2, 3, 4, 5, 6, 7) fmt.Printf("with AutoUnpatch, ByName: %v\n", tmp) }) afterAutoUnpatch := MyTimeFunc(2021, 2, 3, 4, 5, 6, 7) fmt.Printf("after AutoUnpatch: %v\n", afterAutoUnpatch)
Output: original: 2021-02-03 04:05:06.000000007 +0000 UTC patched: 2001-01-01 01:01:01.000000001 +0000 UTC unpatched: 2021-02-03 04:05:06.000000007 +0000 UTC before AutoUnpatch with AutoUnpatch, before mock: 2021-02-03 04:05:06.000000007 +0000 UTC with AutoUnpatch, after mock: 2001-01-01 01:01:01.000000001 +0000 UTC inner AutoUnpatch, before mock: 2001-01-01 01:01:01.000000001 +0000 UTC inner AutoUnpatch, after mock: 2002-02-02 02:02:02.000000002 +0000 UTC with AutoUnpatch, after inner: 2001-01-01 01:01:01.000000001 +0000 UTC with AutoUnpatch, after inner mock333: 2003-03-03 03:03:03.000000003 +0000 UTC with AutoUnpatch, after inner mock444: 2004-04-04 04:04:04.000000004 +0000 UTC with AutoUnpatch, ByName: 2005-05-05 05:05:05.000000005 +0000 UTC after AutoUnpatch: 2021-02-03 04:05:06.000000007 +0000 UTC
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AutoUnpatch ¶
func AutoUnpatch(f func())
AutoUnpatch encapsulates a function with a context, which automatically unpatch all patches applied within function f.
Types ¶
type Patch ¶
type Patch struct {
// contains filtered or unexported fields
}
Patch holds the patch data of a patch target and its replacement.
func PatchByName ¶
PatchByName replaces a function with replacement by it's name. TargetName should be the fully-qualified name of the target function or method. If the target cannot be found or the replacement type does not match, it panics.
func PatchFunc ¶
func PatchFunc(target, repl interface{}) *Patch
PatchFunc replaces a function with replacement. If target or replacement is not a function or their types do not match, it panics.
func PatchMethod ¶
PatchMethod replaces a target's method with replacement. Replacement should expect the receiver (of type target) as the first argument. If the method cannot be found or the replacement type does not match, it panics.
func PatchVar ¶
func PatchVar(targetAddr, repl interface{}) *Patch
PatchVar replaces target's value with replacement. If type of target and repl does not match, it panics.
Example ¶
var someVar = 1234 fmt.Printf("original: %v\n", someVar) patch := PatchVar(&someVar, 2345) fmt.Printf("patched: %v\n", someVar) patch.Delete() fmt.Printf("unpatched: %v\n", someVar) fmt.Printf("before AutoUnpatch\n") AutoUnpatch(func() { fmt.Printf("with AutoUnpatch, before patch: %v\n", someVar) PatchVar(&someVar, 3456) fmt.Printf("with AutoUnpatch, after patch: %v\n", someVar) AutoUnpatch(func() { fmt.Printf("inner AutoUnpatch, before patch: %v\n", someVar) PatchVar(&someVar, 4567) fmt.Printf("inner AutoUnpatch, after patch: %v\n", someVar) }) fmt.Printf("with AutoUnpatch, after inner: %v\n", someVar) // Patch again. PatchVar(&someVar, 5678) fmt.Printf("with AutoUnpatch, patch again: %v\n", someVar) }) fmt.Printf("after AutoUnpatch: %v\n", someVar)
Output: original: 1234 patched: 2345 unpatched: 1234 before AutoUnpatch with AutoUnpatch, before patch: 1234 with AutoUnpatch, after patch: 3456 inner AutoUnpatch, before patch: 3456 inner AutoUnpatch, after patch: 4567 with AutoUnpatch, after inner: 3456 with AutoUnpatch, patch again: 5678 after AutoUnpatch: 1234
func (*Patch) Delete ¶
func (p *Patch) Delete()
Delete resets target to the state before applying the patch.
func (*Patch) Origin ¶
func (p *Patch) Origin() interface{}
Origin returns the original target. For a function, it returns a function which runs the original code. For a variable, it returns the original value of the target variable.
Example ¶
var someVar = 1234 AutoUnpatch(func() { fmt.Printf("before patch, testpkg.A: %v\n", testpkg.A()) fmt.Printf("before patch, someVar: %v\n", someVar) patch1 := Mock().Target(testpkg.A).Return("ExamplePatch_Origin").Build() patch2 := PatchVar(&someVar, 5678) fmt.Printf("after patch, testpkg.A: %v\n", testpkg.A()) fmt.Printf("after patch, someVar: %v\n", someVar) fmt.Printf("after patch, original testpkg.A: %v\n", patch1.Origin().(func() string)()) fmt.Printf("after patch, original someVar: %v\n", patch2.Origin()) })
Output: before patch, testpkg.A: testpkg.a before patch, someVar: 1234 after patch, testpkg.A: ExamplePatch_Origin after patch, someVar: 5678 after patch, original testpkg.A: testpkg.a after patch, original someVar: 1234