
環境変数を介して実行時制御可能なフェイルポイントを追加し、パニック、スリープ、リターン、条件付きエラーパスをトリガーできるGo向けフォールトインジェクションライブラリ。
Golang向けのfailpointsの実装です。フェイルポイントは、ユーザーが制御した方法でエラーを注入できるコードポイントを追加するために使用されます。フェイルポイントは、対応するフェイルポイントがアクティブな場合にのみ実行されるコードスニペットです。
failpoint-ctl を使う)ソースから failpoint-ctl をビルドする
git clone https://github.com/pingcap/failpoint.git
cd failpoint
make
ls bin/failpoint-ctl
フェイルポイントをプログラムに注入します。例:
package main
import "github.com/pingcap/failpoint"
func main() {
failpoint.Inject("testPanic", func() {
panic("failpoint triggerd")
})
}
failpoint-ctl enable でコードを変換する
go build でビルドする
GO_FAILPOINTS 環境変数でフェイルポイントを有効にする
GO_FAILPOINTS="main/testPanic=return(true)" ./your-program
注: GO_FAILPOINTS は InjectCall タイプのマーカーでは機能しません。
go run でテストを実行する場合は、生成された binding__failpoint_binding__.go をコマンドに追加することを忘れないでください。例:
GO_FAILPOINTS="main/testPanic=return(true)" go run your-program.go binding__failpoint_binding__.go
failpoint-toolexec を使う)ソースから failpoint-toolexec をビルドする
git clone https://github.com/pingcap/failpoint.git
cd failpoint
make
ls bin/failpoint-toolexec
フェイルポイントをプログラムに注入します。例:
package main
import "github.com/pingcap/failpoint"
func main() {
failpoint.Inject("testPanic", func() {
panic("failpoint triggerd")
})
}
failpoint-toolexec なしのキャッシュが混ざらないように、別のビルドキャッシュを使用してビルドする
GOCACHE=/tmp/failpoint-cache go build -toolexec path/to/failpoint-toolexec
GO_FAILPOINTS 環境変数でフェイルポイントを有効にする
GO_FAILPOINTS="main/testPanic=return(true)" ./your-program
go run や go test を使うこともできます。例:
GOCACHE=/tmp/failpoint-cache GO_FAILPOINTS="main/testPanic=return(true)" go run -toolexec path/to/failpoint-toolexec your-program.go
フェイルポイントをコメントやその他のものではなく、有効な Golang コードで定義する
フェイルポイントに追加コストはない
フェイルポイントのルーチンは読み書き可能で、コンパイラでチェックされるべきである
フェイルポイント定義によって生成されるコードは読みやすい
注入コードと同じ行番号を維持する(デバッグしやすい)
context.Context による並列テストをサポートする
フェイルポイント
フェイルポイントは、対応するフェイルポイントがアクティブな場合にのみ実行されるコードスニペットです。
failpoint.Disable("failpoint-name-for-demo") が実行された場合、クロージャは決して実行されません。
var outerVar = "declare in outer scope"
failpoint.Inject("failpoint-name-for-demo", func(val failpoint.Value) {
fmt.Println("unit-test", val, outerVar)
})
マーカー関数
それは単なる空の関数です
書きやすく読みやすい
フェイルポイントコードが無効な場合、通常モードではコンパイルできないようにするコンパイラチェックを導入する
マーカー関数リスト
func Inject(fpname string, fpblock func(val Value)) {}func InjectContext(fpname string, ctx context.Context, fpblock func(val Value)) {}func InjectCall(fpname string, args ...any) {}func Break(label ...string) {}func Goto(label string) {}func Continue(label ...string) {}func Fallthrough() {}func Return(results ...interface{}) {}func Label(label string) {}サポートされているフェイルポイント環境変数
フェイルポイントは、以下のパターンの環境変数をエクスポートすることで有効にできます。これは freebsd failpoint SYSCTL VARIABLES と非常によく似ています。
注: InjectCall は環境変数では有効にできません。
[<percent>%][<count>*]<type>[(args...)][-><more terms>]
引数は実行するアクションを指定します。以下から1つを選択できます:
failpoint.Inject を呼び出すことで、呼び出しサイトにフェイルポイントを注入できます。failpoint-name はフェイルポイントをトリガーするために使用され、failpoint-closure は IF ステートメントの本体として展開されます。
failpoint.Inject("failpoint-name", func(val failpoint.Value) {
failpoint.Return("unit-test", val)
})
変換後のコードは次のようになります:
if val, _err_ := failpoint.Eval(_curpkg_("failpoint-name")); _err_ == nil {
return "unit-test", val
}
failpoint.Value は、failpoint.Enable("failpoint-name", "return(5)") によって渡される値で、無視することができます。
failpoint.Inject("failpoint-name", func(_ failpoint.Value) {
fmt.Println("unit-test")
})
または
failpoint.Inject("failpoint-name", func() {
fmt.Println("unit-test")
})
変換後のコードは次のようになります:
if _, _err_ := failpoint.Eval(_curpkg_("failpoint-name")); _err_ == nil {
fmt.Println("unit-test")
}
また、フェイルポイントのクロージャは context.Context を受け取る関数にすることができます。並列テストやその他のケースでフェイルポイントがアクティブかどうかを制御するなど、context.Context を使ってカスタマイズした処理を行うことができます。例:
failpoint.InjectContext(ctx, "failpoint-name", func(val failpoint.Value) {
fmt.Println("unit-test", val)
})
変換後のコードは次のようになります:
if val, _err_ := failpoint.EvalContext(ctx, _curpkg_("failpoint-name")); _err_ == nil {
fmt.Println("unit-test", val)
}
context.Context を無視することもでき、その場合は上記の非コンテキスト版と同じコードが生成されます。例:
failpoint.InjectContext(nil, "failpoint-name", func(val failpoint.Value) {
fmt.Println("unit-test", val)
})
は、以下のようになります:
if val, _err_ := failpoint.EvalContext(nil, _curpkg_("failpoint-name")); _err_ == nil {
fmt.Println("unit-test", val)
}
failpoint.InjectCall を使用して関数呼び出しを注入できます。このタイプのマーカーは failpoint.EnableCall を使用した場合にのみ有効にでき、InjectCall の呼び出しサイトと同じプロセス内で呼び出す必要があります。このマーカーを使用すると、フェイルポイントコードがソースコードを汚染するのを防げます。examples を参照してください。
フェイルポイントは failpoint.WithHook で制御できます。